1,结构体
#include<stdio.h> #include<windows.h> struct S //类型声明 { char name[20]; //名字 int age; //年龄 }; struct S1 { char name[20]; int age; }s1 = { "李四", 25 }; //声明类型的同事定义变量s1 struct S2 { char name[20]; int age; struct S *node; }s2 = {"王五",30,NULL}; //结构体嵌套的初始化 int main() { struct S s = { "张三", 18 }; //初始化 struct S2 s3 = { "周六", 40 }; printf("%s %d\n", s.name, s.age); printf("%s %d\n", s1.name, s1.age); printf("%s %d\n", s2.name, s2.age); printf("%s %d\n", s3.name, s3.age); system("pause"); return 0; }
结果:
结构体内存对齐
结构体内存对齐是非常热门的考点。
那么为什么存在内存对齐?
1.平台原因
不是所有的硬件平台都能访问任意地址上的任意数据的。
2.性能原因
数据结构应该尽可能地在地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要进行两次内存访问;而对其的内存访问仅需要一次访问。
内存对齐如何计算?
我们必须掌握结构体的对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对其到对齐数的整数倍的地址处。(对齐数=编译器默认的一个对齐数与该成员大小的较小值。vs中默认的值为8 Linux中的默认值为4)
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
举例子:
看代码:
#include<stdio.h> #include<windows.h> struct s1 { char a; int b; char c; }; struct s2 { char a; char b; int c; }; struct s3 { double a; char c; int i; }; struct s4 { char a; struct s3 b; double c; }; int main() { printf("%d\n", sizeof(struct s1)); printf("%d\n", sizeof(struct s2)); printf("%d\n", sizeof(struct s3)); printf("%d\n", sizeof(struct s4)); system("pause"); return 0; }
结果:
解释:
2.位段
先来看一个位段类型代码:
#include<stdio.h> #include<windows.h> struct A { int _a : 2; int _b : 5; int _c : 10; int _d : 30; }; int main() { printf("%d\n", sizeof(struct A)); system("pause"); return 0; }
输出的结果为8;
位段有属于自己的特点:
(1)位段的成员必须是int ,unsigned int,signed int。
(2)位段的成员名后边有一个冒号和一个数字。
那么位段的大小是如何计算的?
由于是int类型,所以给位段的内存分配时,先分配四个字节的大小,如果够用,就不会继续分配;如果不够用,比如struct A ,先分配的四个字节不够用,然后在分配四个字节,总共就8个字节的大小。
3.联合
联合也是一种特殊的自定义类型,这中类型定义的变量也包含一系列的成员,但是这些成员公用一块空间(联合体也叫共用体)。
看代码:
#include<stdio.h> #include<windows.h> union Un { char b; int c; }; int main() { union Un a; printf("%d\n", sizeof(a)); system("pause"); return 0; }
输出的结果为4;
联合的成员是公用同一块内存空间,这样一个联合变量的大小,至少是最大成员的大小。
联合可用于求此计算机的大小端存储。
看代码:
#include<stdio.h> #include<windows.h> int daxiaoduan() { union { int b; int c; }un; un.b = 1; return un.c; } int main() { int ret = daxiaoduan();; if (ret = 1) printf("大端\n"); if (ret = 0) printf("小端\n"); system("pause"); return 0; }
联合大小的计算
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
比如:
#include<stdio.h> #include<windows.h> union un1 { char a[5]; int b; }; union un2 { short c[7]; int b; }; int main() { printf("%d\n", sizeof(union un1)); printf("%d\n", sizeof(union un2)); system("pause"); return 0; }
结果:
在un1中,最大成员大小(5)不是最大对齐数(4)的整数倍,所以对齐到第八个字节处。
在un2中,最大成员大小(14)不是最大对齐数(4)的整数倍,所以对齐到第十六字节处。