目录
1.结构体
- 结构体类型的声明
- 结构的自引用
- 结构体变量的定义和初始化
- 结构体内存对齐
- 结构体传参
- 结构体实现位段(位段的填充&可移植性)
1.结构体
-
结构体类型的声明
结构体声明公式
举例说明
特殊类型
匿名结构体类型
匿名结构体类型只能在结构体哪里创建变量(全局变量)
这样也是不对的,这么写编译器认为是错的,因为编译器认为这两个类型是不一样
所以尽量不要写匿名结构体
struct
{
char name[20];
char sex[10];
int age;
char id[15];
}s1;
struct
{
char name[20];
char sex[10];
int age;
char id[15];
}* ps;
int main()
{
ps = &s1;//err,这么写编译器认为是错的,编译器认为这两个地址类型是不一样
return;
}
-
结构的自引用
那我们访问的时候要如何找到下一个结点呢?
此时的结点既需要储存自己的数据,又需要和下一个结点建立联系
- 这时可以这样做
🙈🙈错误案例
这样写是错的,你无法求出sizeof(struct Node)的大小,会无限循环
🥫🥫 正确示范
🐯🐯这样就串起来了
-
结构体变量的定义和初始化
初始化1
初始化2
初始化3
-
结构体内存对齐
下边这几个数是多少呢?
struct S1
{
int a;
char c;
};
struct S2
{
char c1;
int a;
char c2;
};
struct S3
{
char c1;
int a;
char c2;
char c3;
};
int main()
{
printf("%d %d %d", sizeof(struct S1), sizeof(struct S2), sizeof(struct S3));
return;
}
为什么是8,12,12呢?
- struct S1
- struct S2
- struct S3
**************************🥫🥫🥫🥫🥫🥫🥫🥫🥫🥫🥫🥫🥫🥫********************************
1.结构体的第一个成员永远都放在0偏移处
2.从第二个成员开始,以后的每一个成员都要对齐到某个对齐数的整数倍数
(这个对齐数是成员自身大小和默认对齐数的较小值)
ps:
(vs环境下默认对齐数是8
gc环境下没有对齐数,没有对齐数时,对齐数就是成员自身的大小)
3.当成员全部存放进去后
结构体的总大小必须是,所有成员的对齐数中最大对齐数的整数倍如果不够,就浪费空间对齐
-
结构体传参
struct S
{
int data[1000];
int num;
};
struct S s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传地址
return 0;
}
ps: 首选print2函数
-
结构体实现位段(位段的填充&可移植性)
位段的声明和结构是类似的,有两个不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。
例子
A就是一个位段类型,
那位段A的大小是多少?
是 8
原因:上面共2+5+10+30=47个比特位,一个字节八个比特位,按理来说应该是6*8 = 48个比特位
但现在是8*8 = 64,别太贪,已经很棒了
位段的内存分配
1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
举例说明