struct tag//结构体名
{
member - list;//成员列表
}variable - list;//变量列表
举个例子
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
#include <stdio.h>
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};
int main()
{
//按照结构体成员的顺序初始化
struct Stu s = { "张三", 20, "男", "20230818001" };
printf("name: %s\n", s.name);
printf("age : %d\n", s.age);
printf("sex : %s\n", s.sex);
printf("id : %s\n", s.id);
//按照指定的顺序初始化
struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex =
"⼥" };
printf("name: %s\n", s2.name);
printf("age : %d\n", s2.age);
printf("sex : %s\n", s2.sex);
printf("id : %s\n", s2.id);
return 0;
}
特别的,打印结构体一般有两种方式,分别对应‘.’与‘->’操作符。下面我们来举个例子
struct Stu
{
char name[20];
int age;
};
int main()
{
struct Stu s = { "zhangsan",20 };
printf("%s %d\n", s.name, s.age);//使用变量指向
struct Stu* ps = &s;
printf("%s %d\n", ps->name, ps->age);//使用指针指向
return 0;
}
可以看到它们打印的结果是一致的:
在声明结构时,可以不完全声明
比如:
//匿名结构体类型
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], * p;
上面两个结构体在声明是省略了结构体标签(tag)
那么问题来了
//在上⾯代码的基础上,下⾯的代码合法吗?
p = &x;
答案是否定的,编译器会把上⾯的两个声明当成完全不同的两个类型,所以是⾮法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。
在结构中包含一个类型为该结构本身的成员应注意什么呢?
例如,定义一个链表的节点时,应确保链表内使用指针变量来指向下一目标地址的指针
struct Node
{
int data;//-- 数据域
struct Node *next;//--指针域
};
typedef 对匿名结构体类型重命名,也应注意定义的先后顺序,避免混淆
typedef struct
{
int data;
Node* next;//因为Node是对前⾯的匿名结构体类型的重命名产⽣的,但是在匿名结构体内部提前使
//⽤Node类型来创建成员变量,这是不⾏的。
}Node;
typedef struct Node
{
int data;
struct Node* next;
}Node;
首先我们来看两组代码,思考一下它们的结果为何不同?
这就是结构内存对齐导致的差异,下面我们先来了解一下它的基本概念:
1.结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数=编译器默认的⼀个对齐数与该成员变量大小的较小值
-VS 中默认的值为 8
-Linux中gcc没有默认对齐数,对齐数就是成员自身的大小。
3.结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的 整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构 体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。
先来补充一下offsetof这个宏的知识:
它是用来计算结构体成员相较于结构体变量起始位置的偏移量。
我们用一张图来理解
这样便能解释为什么上面的代码存在不同了
同样的,对于内置的结构体,例如
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
int main()
{
struct S4 s4;
/*struct S s2;*/
printf("%zd\n", sizeof(s4));
return 0;
}
代码的结果为
根据内存对齐,我们很容易得到s3的大小为16,如下图
故能得到struct S4 的大小
以上便是结构体的相关内容,欢迎大家在评论取与我交流,点出我的不足,我们共同进步!