结构体的定义
方式一
typedef struct _stu
{
char name[10];
int age;
float score;
int class;
}stu_t;
方式2
struct stu
{
char name[10];
int age;
float score;
int class;
}stu1;
结构体的声明包含了其他的结构体
struct COMPLEX
{
char string[100];
struct SIMPLE a;
};
结构体的声明包含了指向自己类型的指针
struct node
{
char str[10];
struct node *nextNode;
};
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明
A结构体中包含B,B结构体中包含A,最好是定义指针变量struct B *b;
或者struct A *a;
不要定义结构体变量struct B b;
或者struct A a;
//先声明结构体B
struct B;
struct A
{
char str[10];
struct B *b;
};
struct B
{
int i;
struct A *a;
};
结构体内存对齐
找出最大成员类型的长度x,与#pragma pack指定的数值y(默认为8),按照min(x, y)对齐。
- 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
- 结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
- 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
- 简单结构体
struct A
{
char c;
int i;
};//sizeof(struct A) = 8
struct B
{
char c;
int i;
char c1;
};//sizeof(struct B) = 12
struct C
{
char c[2];
int i;
};//sizeof(struct C) = 8
struct D
{
char c[2];
int i;
char c1[5];
};//sizeof(struct D) = 16
- 复杂结构体
#include <stdio.h>
typedef struct _stu1
{
char name[13];
long long age;
float score;
int i;
}stu1_t;
typedef struct _stu2
{
char ch1[2];
char ch2;
int id[3];
float f;
}stu2_t;
int main()
{
printf("stu1_t = %d\n", sizeof(stu1_t));
printf("stu2_t = %d\n", sizeof(stu2_t));
}
/*
输出结果
stu1_t = 32
stu2_t = 20
*/
- 成员包含结构体的结构体
计算结构体大小的时候,需要把里面的结构体拆开再进行计算,以最大成员类型进行内存对齐。
#include <stdio.h>
typedef struct
{
char c;
short b[2];
char c1[7];
}A_t;
typedef struct
{
int i;
struct a
{
char c1[4 + 13];
};
long long l;
}B_t;
typedef struct
{
int i;
A_t a;
long long l;
}C_t;
int main()
{
printf("A_t = %u\n", sizeof(A_t));
printf("B_t = %u\n", sizeof(B_t));
printf("C_t = %u\n", sizeof(C_t));
}
/*
A_t = 14
B_t = 32
C_t = 32
*/
结构体内存构成
4. 成员包含联合体的结构体
typedef struct
{
int ii;
union u1
{
int i;
char s[6];
};
char cc;
}A_t;//sizeof(A_t) = 16
typedef struct
{
char c;
union u
{
int i1;
short s[3];
};
int i;
}B_t;//sizeof(B_t) = 16
以4字节对齐
5. 指定对齐值
- 对齐值小于最大类型成员值
#pragma pack(4)//对齐值为4
struct s1
{
char c;
long long l;
int i;
};//sizeof(struct s1) = 16
对齐值为4,最大类型成员为8,则按4字节对齐
- 对齐值大于最大类型成员值
#pragma pack(8)//对齐值为8
struct s1
{
char c;
int i;
char cc;
};//sizeof(struct s1) = 12
对齐值为8,最大类型成员为4,则按4字节对齐
从网上看见的一种对结构体内存对齐解释方式
typedef struct t1{
char x;
int y;
double z;
}T1;
typedef struct t2{
char x;
double z;
int y;
}T2;
T1: 若从第 0 个字节开始分配内存,则 T1.x 存入第 0 字节,T1.y 占 4 个字节,由于第一的 4 字节已有数据,所以 T1.y 存入第 4-7 个字节,T1.z 占 8 个字节,由于第一个 8 字节已有数据,所以 T1.z 存入 8-15 个字节。共占有 16 个字节。
T2: 若从第 0 个字节开始分配内存,则 T1.x 存入第 0 字节,T1.z 占 8 个字节,由于第一的 8 字节已有数据,所以 T1.z 存入第 8-15 个字节,T1.y 占 4 个字节,由于前四个 4 字节已有数据,所以 T1.z 存入 16-19 个字节。共占有 20 个字节。此时所占字节不是最宽元素(double 长度为 8)的整数倍,因此将其补齐到 8 的整数倍,最终结果为 24。
注意点:结构体作为 函数参数时,用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。