Pointers on C——10 Structures and Unions.11

10.3 Structure Storage Allocation

How are structures actually stored in memory? The diagrams in the previous examples imply that structures contain a lot of empty space. This picture is not entirely accurate. Memory is allocated for each of the members, one after another, in the order given by the member list. Extra memory is used only when needed to get the correct boundary alignment of a member. 

结构在内存中是如何实际存储的呢?前面例子的这张图似乎提示了结构内部包含了大量的未用空间但这张图并不完准确,编译器按照成员列表的顺序个接个地给每个成员分配内存存储成员时需要满足正确的边界对齐要求时,成员之间才能出现用于填充的额外内存空间


To illustrate, consider this structure:

为了说明这点,考虑下面这个结构:


struct ALIGN {

char a;

int b;

char c;

};


On a machine whose integers occupy four bytes and must begin at a byte whose address is evenly divisible by four, this structure would appear like this in memory:

如果某个机器的整型值长度为4 个字节,并且它的起始存储位置必须能够被4 整除,那么这一个结构在内存中的存储将如下所示:


The compiler is forbidden to skip bytes for boundary alignment at the beginning of a structure, so all structures must begin on whatever boundary is required for the most stringent data type. Thus, the member a, shown by the leftmost box, begins at an address divisible by four. The next member is an integer, so three bytes (shown in gray) must be skipped to reach an appropriate boundary. After the integer comes the last character.

系统禁止编译器在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有结构的起始存储位置必须是结构中边界要求最严格的数据类型所要求的位置。因此,成员a (最左边的那个方框)必须存储于一个能够被4 整除的地址。结构的下一个成员是一个整型值,所以它必须跳过3个字节(用灰色显示)到达合适的边界才能存储。在整型值之后是最后-个字符。


If a second variable of the same type were declared, it would have to begin on a boundary of four as well, so three more bytes would be skipped at die end of the structure. Thus, each structure would require twelve bytes of memory but would only use six of them, which is not very good utilization.

如果声明了相同类型的第2 个变量,它的起始存储位置也必须满足4 这个边界,所以第1 个结构的后面还要再跳过3 个字节才能存储第2 个结构。因此,每个结构将占据12 个字节的内存空间但实际只使用其中的6 个,这个利用率可不是很出色。


You can minimize the space lost to boundary alignment in structures by rearranging the member list in the structure declaration so that the members with the strictest boundary requirements appear first and those with the weakest requirements appear last. For example, this structure

你可以在声明中对结构的成员列表重新排列,让那些对边界要求最严格的成员首先出现,对边界要求最弱的成员最后出现。这种做法可以最大限度地减少因边界对齐而带来的空间损失。例如,下面这个结构


struct ALIGN2 {

int b;

char a;

char c;

};


contains the same members as the previous structure, but requires only eight bytes, a savings of 33%. The two characters can be stored adjacent to one another, so the only wasted space is the two bytes skipped after the structure.

所包含的成员和前面那个结构一样,但它只占用8 个字节的空间,节省了33% 。两个字符可以紧挨着存储,所以只有结构最后面需要跳过的两个字节才被浪费。


There may be good reasons why we might not want to rearrange the members of a structure to reduce the memory lost to alignment. For example, we may want to keep related structure members together for easier maintenance and readability. Lacking any such reasons, however, the members of a structure should be arranged according to their boundary needs in order to minimize the memory that will be lost to alignment.

有时,我们有充分的理由,决定不对结构的成员进行重排以减少因对齐带来的空间损失。例如,我们可能想把相关的结构成员存储在一起,提高程序的可维护性和可读性。但是,如果不存在这样的理由,结构的成员应该根据它们的边界需要进行重排,减少因边界对齐而造成的内存损失。


When the program will be creating hundreds or thousands of the structures, the need to reduce wasted memory can become more important than readability concerns.In this type of situation, adding comments to the declaration may help regain much of the lost readability.

当程序将创建几百个甚至几千个结构时,减少内存浪费的要求就比程序的可读性更为急迫。在这种情况下,在声明中增加注释可能避免可读性方面的损失。


sizeof gives the total size of a structure, which includes any bytes that are skipped for boundary alignment. If you must determine the actual position of a member in a structure, taking into account boundary alignment, use the offsetof macro (which is defined in stddef.h).

sizeof 操作符能够得出一个结构的整体长度,包括因边界对齐而跳过的那些字节。如果你必须确定结构某个成员的实际位置,应该考虑边界对齐因素,可以使用offsetof 宏(定义于stddef.h) 。


offsetoff( type, member ) type is the type of the structure, and member is the name of the member you want. The result is a size_t value specifying the number of bytes from the beginning of the structure where the specified member begins. For example, with the declaration above,offsetof( struct ALIGN, b )returns four.

type 就是结构的类型, member 就是你需要的那个成员名。表达式的结果是个size_t值,表示这个指定成员开始存储的位置距离结构开始存储的位置偏移几个字节。例如,对前面那个声明而言,offsetof( struct ALIGN, b )的返回值是4 。

上一章 Pointers on C——10 Structures and Unions.10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值