目录
一、结构体声明与自引用
二、结构体内存对齐
为什么要内存对齐?
计算结构体的大小
offsetof 宏的实现
三、位段
四、枚举类型enum
五、联合体union
联合体应用
struct
{//没有标签,匿名结构体类型,属于不完全声明
int a;
char b;
float c;
}x;//这里x是全局变量
struct
{
int a;
char b;
float c;
}a[20], * p;//这里是结构体指针一个问题:
p=&x,合法吗?
答:不合法,编译器会认为这是两个结构体,所以这两边是驴头不对马嘴
结构体自引用
struct Node
{
int data;
struct Node next;
};
//可行否?
如果可以,那sizeof(struct Node)是多少?答:不行,int-4 下面又是4,死循环套了,所以要用指针,指向同类型节点的下一个地方,而指针类型大小是4/8。所以要这样写:
struct Node
{
int data;
struct Node* next;
};
tips:
typedef struct
{
int data;
Node* next;
}Node;
//这样写代码,可行否?是先有struct还是先有Node呢
//解决方案:先有struct
typedef struct Node
{
int data;
struct Node* next;
}Node;tips:
结构体传参最好传地址,这样可以控制实参的改变是否影响形参,如果传结构体会导致实参的改变不能影响形参,因为是相当于开辟了2块存储空间。空间开销大,性能低。
1.某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.为了便于访问,不对齐可能会遇到一个in提取2次的情况。
1.int有4个字节,VS默认对齐数是8,选最小的4,而且它要对齐在最小倍数上,
2.char有一个字节,倍数是1,第一个成员在与结构体变量偏移量为0的地址处。
3.最后结果9个空间,还要取它最大对齐数(每个成员变量都有一个对齐数)的最小整数倍。最大对齐数这里是4。
例子1:
例子2:
由于这个特点,可以自己想想怎么放会比较节约空间。
还可以通过修改默认对齐数:
#pragma pack(1)//设置默认对齐数为1
struct S2
{};
#pragma pack()//取消设置,还原VS默认对齐数
例子3:
s5进行了结构体嵌套,这里的结果是16的整数倍还是8的整数倍?
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
答:是8
offsetof可以看结构体成员变量相对起始位置(首地址)的偏移量,
程序结果为0 4 8
#include
#include
struct stu
{
int a;
char b;
double c;
};
#define OFFSETOF(struct_type,mem_name) (size_t)&(((struct_type*)0)->mem_name)
int main()
{
printf("%d\n", OFFSETOF(struct stu, a));
printf("%d\n", OFFSETOF(struct stu, b));
printf("%d\n", OFFSETOF(struct stu, c));
return 0;
}
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};位段成员必须是 int unsigned 或signed int
位段的大小要看内存分配
1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
例:1:
说明:
大小端是字节序,一个字节内部顺序是与大小端无关的
跟结构相比,位段可以达到同样的效果(因为它可以分配空间大小),但是可以很好的节省空间,但是有跨平台的问题存在。
例子2:
16位-----int-----2个byte-----16bit
32位-----int-----4个byte-----32bit
enum优势:
用#define RED 1也行,但是它会在预编译阶段将RED进行转化为1,在调试时我看到1不会想到RED,不便于调试,enum可以解决这个问题。
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
//联合类型的声明
union Un
{
char c;
int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));
判断大小端存储:
结果是12,不是10,4,因为short对齐数是2,int是4,要满足第2点,最小4的倍数是12.
1. 联合的大小至少是最大成员的大小。
2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
最后的打印结果表明:
union共有一块内存空间,改变一个会影响另外一个。
总结
如有错误,希望各位父老乡亲及时指正。