结构、联合、位字段
1、结构体空洞
结构字段在存储器中并不一定是挨着摆放的,有时两个字段之间会有小的空隙。
因为计算机总希望数据能对齐字边界,如果计算机的字长是32位,就不希望某个变量跨越32位的边界保存。
因为计算机按字从存储器中读取数据,如果某个字段跨越了多个字,CPU就必须读取多个存储单元,并以某种方式把督导的值合并起来。会很慢。
2、匿名结构
匿名结构就是没有名字的结构,
typedef struct { … } spider_man;
有一个叫spider_man的别名,但没有结构名,很多时候,如果创建了别名,也就不需要结构名了。
3、指定初始化器
可以用“指定初始化器”按名设置结构和联合字段,属于c99标准。绝大多数现代编译器都支持“指定初始化器”,但如果c语言的变种,可能不支持(比如:c++不支持)
typedef truct
{
const char *color;
int gears;
int height;
}bike;
bike b = {.height = 17, .gears = 23};
4、结构体初始化
margarita m = {2.0, 1.0, {0.5}}; //成功编译
margaruta m;
m = {2.0, 1.0, {0.5}}; //不能编译,因为只有把{2.0, 1.0, {0.5}}和结构声明写在一行里,编译器才知道它代表结构,否则,编译器会认为是数组。
5、枚举记录联合中保存了什么值
编译器不会记录你在联合中设置或读取过哪些字段。我们完全可以设置一个字段,读取另一个字段,但有时这会造成很严重的后果。
可以通过创建枚举,记录我们在联合中保存了什么值。
#include <stdio.h>
typedef enum
{
COUNT,
POUNDS;
PINTS
}unit_of_measure;
typedef union
{
short count;
float weight;
float volume;
}quantity;
typedef struct
{
const char *name;
const char *country;
quantity amount; //联合
unit_of_measure units; //枚举
}fruit_order;
void display(fruit_order order)
{
printf("This order contains");
if (order.units == PINTS)
{
printf("%2.2f pints of %s\n, order.amount.volume, order.name");
}else if (order.units == POUNDS)
{
printf("%2.2f lbs of %s\n", order.amount.weight, order.name);
}else
{
printf("%i %s", order.amount.count, order.name);
}
}
int main()
{
fruit_order apples = {"apples", "England", .amount.count = 144, COUNT};
fruit_order strawberries = {"starawberries", "Spain", .amount.weight = 17.6, POUNDS};
fruit_order oj = {"orange juice", "U.S.A", .amount.volume = 10.5, PINTS};
display(apples);
display(strawberries);
display(oj);
return 0;
}
6、位字段(bitfield)
扫描二维码关注公众号,回复:
1592007 查看本文章
如果编译器发现结构中只有一个位字段,还是会把它填充成一个字,多个位字段总是结合在一起。
位字段不仅仅是为了节省空间,如果要读取底层的二进制信息,位字段会非常有用。比如读写某类自定义二进制文件。
位字段应该声明成unsigned int。