对于复杂的数据类型(例如学生、汽车等),C 语言容许咱们将多种数据封装到一块儿,构成新类型。web
跟面向对象语言中的对象相比,结构体只能包含成员变量,不支持操做。svg
#include <stdio.h> #include <string.h> struct People { int age; char name[100]; // 这里若是用指针,下面用 strcpy 赋值时会报段错误 }; // 分号必须有 int main() { struct People p = {20, "lisi"}; // 使用时,struct People 是一个总体 printf("%d, %s\n", p.age, p.name); // 用点访问结构体成员 struct People *pp = &p; pp->age = 88; strcpy(pp->name, "jack"); // C 语言须要用 strcpy 函数实现字符串拷贝 printf("%d, %s\n", p.age, p.name); return 0; }
结构体变量声明后,能够直接用句点形式访问。函数
struct People p = {20, "lisi"}; p.age = 88;
定义指向结构体的指针后,能够经过箭头来访问成员变量。spa
struct People p = {20, "lisi"}; struct People * pp = &p; pp->age = 88; // 等价于 (*pp).age
对于 32 位数据总线的机器(例如 80386),虽然对内存仍然是按照字节寻址,但每次内存操做都固定传输 32 位数据。若是每次数据传输都连续且不重叠,效率是最高的。因此操做系统把内存按照数据总线的位数划分为独立单元,对于 32 位数据总线的机器每一个单元是 4 个字节。每一个单元都完整的分配给一个程序。操作系统
C 语言的 struct 结构体中,能够放各类类型、不一样长度的数据,能够看作一个数据包。为了在程序内部提升内存访问效率,也须要对齐内存。指针
下面的示例,struct People 中的第一个变量 sex 会对齐内存,第二个变量 age 紧随其后,总共占了三个字节,空余一个字节。以后的 no 占用 4 个字节,若是直接放在 sex 后面保存,则访问 no 时须要两次对内存的操做。为了提升时间效率,C 编译器会把 no 变量对齐内存,这样 no 跟 sex 之间会有一个字节的空白。code
#include <stdio.h> struct People { char sex; // 1 字节 short age; // 2 字节,此时两字节对齐,前面空一个字节 int no; // 4 字节,此时4字节对齐,前面空一个字节 }; int main() { struct People p = {'m', 66, 1234567}; printf("%d\n", sizeof(p)); // 8 个字节 }
下面的例子中,少了一个变量,但由于字节对齐的缘由,存储空间并无减小:xml
#include <stdio.h> struct People { char sex; // 1 个字节 int no; // 4 个字节,前面空 3 个字节 }; int main() { struct People p = {'M', 1234567}; printf("%d\n", sizeof(p)); // 仍是 8 个字节 }
而这个例子中,由于结构体中变量的顺序发生改变,致使空间膨胀:对象
#include <stdio.h> struct People { char sex; // 1 个字节 int no; // 4 个字节,前面空 3 个字节 short age; // 2 个字节,后面空 2 个字节 }; int main() { struct People p = {'m', 1234567, 66}; printf("%d\n", sizeof(p)); // 这里是 12 个字节 }