本文共 3507 字,大约阅读时间需要 11 分钟。
1、定义一个结构体(顺便实例结构体变量):
struct tag(结构体类型名) //struct + tag 这两者共同构成了结构体类型 单独的tag(结构体类型名) 不能称之为结构体类型{ 成员列表}(结构体变量名);
2、定义的同时使用typedef(相当于定义结构体 + 为结构体起新名字)
typedef struct tag(结构体类型名) //struct + tag(结构体类型名) == 结构体类型{ 成员列表}mystruct(结构体类型);此时mystruct == struct tag实例化时: 1、C中: struct tag a; //struct + tag 这两者共同构成了结构体类型 单独的tag(结构体类型名) 不能称之为结构体类型 mystruct a; //mystruct(结构体类型) = struct +结构体类型名2、C++中 tag a; 合理 tag和mtstruct均是结构体类型 mystruct a; 合理
结构体类型的定义格式为:strcut结构体名{成虽说明列表};
结构体变量的定义有3种形式: 1、定义结构体型的同时定义结构体变量 如:strcut结构体名{成员说明列表}变量; 2、先定义一个结构体类型,然后使用该类型来定义结构体变量, 如:strcutstudent{成员说明列表}:student变量; 3、定义一个无名称的结构体类型的同时定义结构体变量 如:strcutstudent{成员说明列表}变量;如果在函数内声明→作用域仅限函数内部
可以只初始化一个成员,也可以任意顺序初始化struct boot gift = { .value=25.99, //使用,分隔 .author="Jime", 0.25 //新的float值0.25替代了旧的值25.99}
意义:内存对齐可以大大提升内存访问速度,是一种用空间换时间的方法。
(内存不对齐会导致每次读取数据都会读取两次,使得内存读取速度减慢。)1、数据成员自身的对齐值:
2、结构体/类的自身对齐值:其成员中自身对齐值最大的那个值。 3、对齐系数:#pragma pack (value)时的指定对齐值value。(VS中默认的值为8;linux中的默认值为4。) 4、数据成员、结构体/类的有效对齐值N:自身对齐值和指定对齐值中小的那个值。仅long和point的长度受到系统环境的影响
1、第一个成员的首地址为0.
2、其余成员的首地址是对齐数的整数倍,对齐数=min(对齐系数,成员自身长度) 3、结构体的总大小,为所有最大对齐数(含嵌套结构体的对齐数)的整数倍。修改默认对齐数:
预处理指令: #pragma pack(?) 例如:#pragma pack(4)struct{ char a[10]; 4(char a[4])+4(char a[4]) +4(char a[2] + 2字节)int b; 4(int)short c[3]; 4(short[2])+4(short[1] + 2字节空余)} 故整体结构体的内存对齐为24字节1.下面的结构体大小分别是多大(假设32位机器)?struct A { char a; //1char b; //1char c; //1};//进行整体对齐,最大类型为1 <对齐系数4,按1整体对齐,所以1+1+1=3 struct b { int a; 4char b; 1short c; 2}; 进行整体对齐,最大类型为4 1+2="3<4" 对齐4 所以4+4="8" c char 1int 4short 1<4(对齐4) 4="4" 2<4(对齐4) 所以4+4+4="12" #pragma pack(2)struct d 1> 对齐系数n(2),所以按2整体对齐 1<2(对齐2)4>2(2的倍数) 2=2 所以2+4+2=8 //4行(每行2字节)// 1字节char 空白1字节// int前半2字节// int后半2字节// short2字节2. 有一个如下的结构体:struct A{ long a1; short a2; int a3; int *a4;}; 答案及解析:2464位编译器下:指针8字节(一定不能忘记),题目不说默认4字节对齐long a1; //8short a2; //2 8+2=10(不是4的倍数)对齐到4的倍数12int a3; //4 4+12=16(4的倍数)int *a4; //8 8+16=24(4的倍数)//6行// long前4字节// long后4字节// short2字节 空白2字节// int4字节// point前4字节// point后4字节 3.在32位cpu上选择缺省对齐的情况下,有如下结构体定义:struct A{ unsigned a : 19; unsigned b : 11; unsigned c : 4; unsigned d : 29; char index;};则sizeof(struct A)的值为16字节题目不说,默认linux对齐系数=4字节对齐19+11=30<32bit 44+29=33>32bit 4+41byte=8bit 1 对齐到 44+4+4+4=16//4行(对齐4字节)// a19位 b11位 空白2位// c4位 空白28位// d29位 空白3位// char1字节 空白3字节 对齐系数4,按1整体对齐,所以1+1+1=3>
typedef struct bb //sizeof(BB) == 16字节{ //起始地址对齐值 int id; //4=min(linux默认对齐系数4,int长度4) double weight; //4=min(linux默认对齐系数4,double长度8) float height; //4=min(linux默认对齐系数4,float长度4)}BB;//4行,每行4=double对齐值4= min(linux默认对齐系数4,double长度8)// int4字节// double前4字节// double4字节// float4字节typedef struct aa{ char name[2]; int id; double score; short grade; BB b; }AA;//9行,每行4字节 此结构体的对齐值 = 该结构体中最大的对齐值,即4// char2字节 空白2字节// int4字节// double前4字节// double后4字节// short2字节 空2字节// 4行BB(每行4字节) BB成员的对齐值 = min(linux对齐参数4,BB长度16) = 4
柔性数组,它只能放在结构体末尾,是申明一个长度为0的数组,就可以使得这个结构体是可变长的。
例如:char data[0];
char data[]; //[]中没有或者0
对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配 请仔细理解后半部分,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!
对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等: 注意:构造缓冲区就是方便管理内存缓冲区,减少内存碎片化,它的作用不是标志结构体结束,而是扩展 柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间)。意义:1、方便管理内存缓冲区
2、减少内存碎片化 3、把单一元素的数组放在一个struct的尾端,使得每个struct对象可以拥有可变大小的数组。typedef struct list_t{ struct list_t *next; struct list_t *prev; char data[0]; 也可以写成char data[]; 本身不占内存和内存对齐 区别:char data[1];表示长度为1的数组}list_t;
转载地址:http://xyhrn.baihongyu.com/