在C语言中的结构体用来将相关的数据集合到一个组合变量中。这项技术有几个优点:
1. 通过展示定义在结构体内的数据是紧密相联的来使代码变得清晰明了。
2. 它使传递数据给函数变得简单。代替单独地传递多个变量,它通过传递一个单元来传递多个变量。
3. 它增加了代码的局部性 。
从汇编语言的观点看,结构体可以认为是拥有不同大小的元素的数组。而真正的数组的元素的大小和类型总是一样的。如果你知道数组的起始地址,每个元素的大小和需要的元素的下标,有这个特性就能计算出这个元素的地址。
结构体中的元素的大小并不一定要是一样的(而且通常情况下是不一样的)。因为这个原因,结构体中的每个元素必须清楚地指定而且需要给每个元素一个标号(或者名称),而不是给一个数字下标。
在汇编语言中,结构体中的元素可以通过和访问数组中的元素一样的方法来访问。为了访问一个元素,你必须知道结构体的起始地址和这个元素相对于结构体的相对偏移地址。但是,和数组不一样的是:不可以通过元素的下标来计算该偏移地址,结构体的元素的地址需要通过编译器来赋值。
例如,考虑下面的结构体:
struct S {
short int x; /* 2个字节的整形 */int y; /* 4个字节的整形 */double z; /* 8个字节的浮点数 */};
图7.1展示了一个S结构体变量在电脑内存中是如何储存的。ANSIC标准规定结构体中的元素在内存中储存的顺序和在struct定义中的顺序是一样的。它同样规定第一个元素需恰好在结构体的起始地址中(也就是说偏移地址为0)。它同样在stddef.h头文件中定义了另一个有用的宏offsetof()。这个宏用来计算和返回结构体中任意元素的偏移地址。这个宏携带两个参数,第一个是结构体类型的变量名,第二个是需要得到偏移地址的元素名。因此,图7.1中的,offsetof(S, y)的结果将是2。
内存地址对齐
如果在gcc编译器中你使用offsetof宏来得到y的偏移地址,那么它们将找到并返回4,而不是2!为回想一下一个地