文章目录
- 一、结构体
- 1.结构体的声明和结构体变量的定义
- 2.结构体变量初始化
- 3. 访问结构体成员
- 4.结构体的内存对齐
- 二、联合(共用体)
- 总结
一、结构体
结构体是一组元素类型不同的元素的集合
1.结构体的声明和结构体变量的定义
结构体的声明包含三个部分,标记名(tag),成员列表(member-list),变量列表(variable-list)。
假如我们要声明一个学生类型,如下:
如果我们要定义变量,我们有两种方式。
- 用结构体类型直接定义变量
- 在变量列表中定义变量
如下:
//在变量列表中定义变量s1,s2
struct Student
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}s1; s2;
int main()
{
//使用结构体类型定义变量s3
struct Student s3;
return 0;
}
除此外,我们也可以是匿名声明(不完全声明),如下:
//不完全声明
struct
{
char c;
short b;
int a;
};
在此情况下,我们要定义变量,只能在变量列表中定义,因为我们并不知道该结构体的类型。
如下:
//定义变量s1,s2,s3
struct
{
char c;
short b;
int a;
}s1; s2; s3;
如果我们不完全声明两个完全相同的结构体,编译器会认为这两个结构体的类型不同。
如下:
//定义变量s1,s2,s3
struct
{
char c;
short b;
int a;
}s1; s2; s3;
//定义指针ps
struct
{
char c;
short b;
int a;
}*ps;
int main()
{
ps = &s1;
return 0;
}
2.结构体变量初始化
对于结构体变量的初始化,有两种方式。
- 可以在变量列表中初始化变量
struct Student
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}s1 = { "李四", 20, "男", "123456" };
- 用类型定义时,初始化变量
struct Student
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};
int main()
{
struct Student s1 = { "李四", 20, "男", 123456 };
return 0;
}
3. 访问结构体成员
对于结构体变量访问其成员,我们用 . 操作符进行访问。
对于结构体指针变量访问其所指向的成员,我们用 -> 操作法进行访问。
如下:
struct A
{
char a;
int b;
};
int main()
{
struct A a = { 0 };
struct A* pa = &a;
a.b = 10;
printf("%d\n", a.b);
pa->b = 20;
printf("%d\n", pa->b);
return 0;
}
结果如下:
4.结构体的内存对齐
要介绍结构体的内存对齐,就不得不计算结构体的大小了。
如下结构体的大小是什么?
struct A
{
char a;
int b;
char c;
};
int main()
{
printf("%d\n", sizeof(struct A));
return 0;
}
答案是12,这就是因为结构体要内存对齐。
想要知道12是如何计算的,我们就要掌握关于对齐数的相关规则。
- 第一个结构体成员永远在地址偏移量为0处。
- 其它成员变量要对齐到它的对齐数的整数倍的地址处
- 结构体的总大小为最大对齐数(其成员变量的对齐数)的整数倍
- 如果嵌套了结构体,嵌套的结构体对齐到字节的最大对齐数的整数倍处,结构体的整体大小就是最大对齐数(嵌套的结构体也是该结构体的成员)的整数倍
对齐数 = 编译器默认的对齐数 与 该成员的大小的较小值。如果编译器没有默认对齐数,那么对齐数就是成员本身的大小。
至此,我们就知道12是如何得到。但为什么要有内存对齐?
-
平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据;某些硬件平台只能在某些地址处取某些特 定类型的数据。 -
性能原因
数据结构(尤其是栈)应该尽可能的在自然边界上对齐。
为了访问未对齐的内存大小,处理器需要做两次内存访问;而对齐的内存访问仅需要一次访问。
二、联合(共用体)
共用体顾名思义就是该类型的成员使用同一块内存空间。
如下:
声明联合体类型union A,其成员是 char a,int b。
union A
{
char a;
int b;
};
那么其大小是多少?
union A
{
char a;
int b;
};
int main()
{
printf("%d\n", sizeof(union A));
return 0;
}
答案是4,为什么?
- 联合体的大小至少是其最大成员的大小
- 联合体的大小还要是其对齐数的整数倍
如上图所述,其成员a和b公用第一个字节,如果我们在使用成员a时,一起使用成员b,那么a = 多少?
union A
{
char a;
int b;
};
int main()
{
union A un = { 0 };
un.a = 1;
un.b = 10;
printf("%d\n", un.a);
return 0;
}
答案是a = 10。我们只需要看内存的变化即可。
总结
以上就是我对于结构体,
联合体知识的总结。