目录
结构体基础
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.结构体声明
struct tag //结构体类型名
{
member-list; //成员变量(列表)
}variable-list;//变量列表
举个栗子
struct stu
{
char name[20];
char sex[5];
int age;
};
上述就是结构体类型有了类型我们就可以创建结构体变量了
struct stu
{
char name[20];
char sex[5];
int age;
}s2,s3;//全局变量
struct stu s5;//全局变量
int main()
{
struct stu s1;//局部变量
return 0;
}
在声明结构的时候,可以不完全的声明
struct
{
int a;
char c;
double d;
}sa;//注意变量只能在这定义(匿名结构体变量)
2.结构的自引用
struct Node
{
int data;
struct Node* next;
};
要注意结构体不能嵌套自己要使用请使用指针(禁止套娃)
typedef struct Node
{
int data;
struct Node* next;
}Node;
在使用typedef重命名结构体时内部不能使用修改后的名字要使用重命名前名字
3.结构体变量的定义和初始化
直接上栗子
struct stu
{
char name[20];
char sex[5];
int age;
};
struct Data
{
struct stu s;
char c;
double b;
};
int main()
{
struct Data sd = { {"lisi","nan",20},'a','3.14' };
}
4.结构体成员访问(.与->的使用)
结构体内存对齐
计算结构体的大小
struct stu
{
int a;
char c;
double d;
};
int main()
{
printf("%d", sizeof(struct stu));//结构体大小多少?
return 0;
}
我们可以先算算 int大小为4,char大小为1,double大小为8 即4+1+8=13结果对嘛?我们验证一下
可以看到结果竟然是16,为什么?
好接下来我们就来说说为什么和我们预想不同在这之前我们先了解一个库函数 offsetof
offsetof是计算结构体成员相较于起始位置的偏移量
结构体对齐规则
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认对齐数 与 该成员大小的较小值。
VS中默认对齐数为8
Linux没有默认对齐数,对齐数就是成员自身大小
3. 结构体总大小为最大对齐数的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
为什么要存在内存对齐
1. 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特
定类型的数据,否则抛出硬件异常。
2. 性能原因 :
数据结构 ( 尤其是栈 ) 应该尽可能地在自然边界上对齐。
原因在于:为了访问未对齐的内存处理器需要作两次内存访问;而对齐的内存访问仅需要一次访
问。
结构体的内存对齐是拿空间来换取时间的做法。
让占用空间小的成员尽量集中在一起。
修改默认对齐数
需要使用#pragma pack()可以修改默认对齐数 直接看代码
百度面试题
写一个宏,计算结构体中某变量相对于首地址的偏移
#define OFFSETOF(s_name,n_name) (int)&(((s_name*)0)->n_name)
struct stu
{
int a;
char c;
double d;
};
int main()
{
printf("%d\n", OFFSETOF(struct stu, a));//0
printf("%d\n", OFFSETOF(struct stu, c));//4
printf("%d\n", OFFSETOF(struct stu, d));//8
return 0;
}
解释一下我们把0强转为结构体指针->成员 再取地址就是偏移量但此时类型为结构体类型我们就还需要强转为整型
//#define OFFSETOF(s_name,n_name) (int)&(((s_name*)0)->n_name)
// (int)&(((struct s*)0)->a)
以上就是有关结构体的总结觉得有帮助就点点赞吧 蟹蟹了