C语言结构体
C语言结构体最全面讲解,小白看完就会运用,轻松玩转结构体
结构基础知识
聚合数据类型能够同时存储超过一个的单独数据。C提供了两种类型的聚合数据类型,分别是数组和结构体。数组是相同元素的集合,它的每个元素是通过下标引用或指针间接访问的。结构体也是一些值的的集合,这些值称为它 的成员,但一个结构的成员可能具有不同的类型。
数组元素可以通过下标访问,这是因为数组元素长度相同,但在结构体中并非如此,由于每个成员的类型可能不同,那么长度也就可能不同,所以就不能通过下标来访问。但是结构体成员都有自己的名字,他们是通过名字访问的。另外,结构体在表达式中使用时,不能被替换为指针。结构体变量也无法使用下标来选择特定的成员。
结构体的声明
这个结构体创建了结构体变量x,结构体包含了2个成员:整型a,字符ch。
结构体声明哪些可以省略?
标签A可以省略,那么就是匿名结构体类型,但不建议。在声明时可以没有结构体变量x,如果有,那么该变量为全局变量。如果在main函数中,就是局部变量。
如下:
struct A x;
int x;
struct A 相当于int ,也就是类型,属于结构体类型,x是结构体变量。
a[20]包含了20个结构,p是一个指针,它指向结构。
上面两个结构都忽略了结构体标签(如A),那么这个语句成立吗?p=&x?
警告:这两个声明被编译器当做两种截然不同 的类型,即使成员相同。所以,变量a,p,x,类型不同,不可p=&x。
注:用typedef后,simple是个类型名,可以创建变量。
访问结构体成员
在学习中有迷茫不知如何学习的朋友小编推荐一个学c/c++的学习q u n 六四三;三九二;二二零;无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!内有开发工具,很多干货和技术资料分享!
通过.操作符访问成员:
通过->进行访问:
两者结果为:10 zhangsan
结构体自引用
我们已经知道在结构体中可以包含数组,指针,标量,结构体...那么结构体里面能不能包含该结构体本身呢?
不可以,因为不知道结构体大小,无法开辟空间存y。
正确的结构体自引用如下:
因为struct stu *y是指针类型,即为4个字节,可以开辟空间。
结构的不完整声明
偶尔,必须声明一些相互之间存在依赖的结构。即,一个结构包含了另一个结构的一个或多个成员。和自引用一样,至少一个结构必须在另一个结构中以指针的形式存在。问题在于声明部分:如果每个结构体都引用了其他 结构的标签,哪个结构应该首先声明?
这个问题的解决方案是使用不完整声明,它声明一个作为结构标签的标识符。然后,把这个标签用在不需要知道这个结构的长度的声明中,如声明指向这个结构的指针。
结构体变量的定义和初始化
结构的初始化方式和数组初始化很相似。一个位于一对花括号内部,由逗号分隔的初始值列表可用于结构的初始化。这些值根据结构成员列表的顺序写出。
注:数组不可以整体赋值,可整体初始化。同理,结构体不可整体赋值,可以整体初始化。结构体地址数值等于第一个成员地址数值。
结构体内存对齐
为什么存在内存对齐?
1.平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据;某些硬件平台只能在某些地址处取某些特定类型的数据,否则就抛出硬件异常。
2.性能原因:
数据结构(尤其是栈)应该尽能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存访问需要访问一次。
图如下:
结构体对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数=编译器默认的对齐数与该成员大小的较小值。VS中默认对齐数为8,linux默认对齐数为4.
3.结构体总大小为最大对齐数(每个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
那么首先看一道题:
通过内存对齐规则,答案肯定不是6,答案是12,解释如下:
再看其他例子:
结果为8。1+1+2+4=8,8是最大对齐数4的倍数。
结果为16。8+1+3+4=16,16是最大对齐数4的倍数。
结果为32。1+7+16+8=32,32是最大对齐数8的倍数。
结构体传参
我们知道数组传参会发生降级,那么结构体会不会降级呢?
结构体传参有两种形式,一个是传结构体,一个是传地址,但是建议选择传地址。因为在栈帧知识中,函数传参,是需要压入栈的,但是如果传结构体对象时,结构体过大,所占空间也就过大,会导致性能下降。