1

结构的成员按照它们在声明中出现的顺序在结构内分配,并且具有升序地址。

我面临以下困境:当我需要声明一个结构时,我是否

(1) 对字段进行逻辑分组,或

(2)按大小递减顺序,节省RAM和ROM的大小?

这是一个示例,其中最大的数据成员应该在顶部,但也应该与逻辑连接的分组colour

struct pixel{
    int posX;
    int posY;

    tLargeType ColourSpaceSecretFormula;
    char colourRGB[3];
}

结构的填充是不确定的(即依赖于实现),因此我们不能可靠地对结构元素进行指针运算(我们不应该:想象有人根据自己的喜好重新排序字段:BOOM,整个代码停止工作)。

-fpack-structs在 gcc 中解决了这个问题,但有其他限制,所以让我们把编译器选项排除在外。

另一方面,代码首先应该是可读的。应不惜一切代价避免微优化。

所以,我想知道,为什么结构的成员按标准排序,让我担心以特定方式排序结构成员的微优化?

4

3 回答 3

3

编译器受到几个传统和实际限制的限制。

转换后指向结构的指针(标准称其为“适当转换”)将等于指向结构第一个元素的指针。这通常用于在消息传递中实现消息的重载。在这种情况下,结构的第一个元素描述了结构其余部分的类型和大小。

最后一个元素可以是动态调整大小的数组。甚至在官方语言支持之前,这已经在实践中经常使用。您分配sizeof(struct) + length of extra data并可以访问最后一个元素作为具有您分配的许多元素的普通数组。

这两件事迫使编译器在结构中具有第一个和最后一个元素,其顺序与声明它们的顺序相同。

另一个实际要求是每次编译都必须以相同的方式对结构成员进行排序。一个聪明的编译器可以做出决定,因为它看到一些结构成员总是被彼此靠近访问,它们可以以一种使它们最终进入缓存行的方式重新排序。这种优化在 C 中当然是不可能的,因为结构通常在不同的编译单元之间定义一个 API,我们不能只是在不同的编译中以不同的方式重新排序。

考虑到这些限制,我们能做的最好的事情是在 ABI 中定义某种打包顺序,以尽量减少不触及结构中第一个或最后一个元素的对齐浪费,但这会很复杂、容易出错并且可能不会买很多。

于 2013-04-25T12:55:56.107 回答
2

如果您不能依赖排序,那么编写将结构映射到硬件寄存器、网络数据包、外部文件格式、像素缓冲区等的低级代码将更加困难。

此外,一些代码使用了一个技巧,它假设结构的最后一个成员是内存中地址最高的,以表示更大数据块的开始(在编译时大小未知)。

于 2013-04-25T12:13:01.673 回答
1

重新排序结构的字段有时可以在数据大小和代码大小方面产生良好的收益,尤其是在 64 位内存模型中。这里举个例子来说明(假设常见的对齐规则):

struct list {
   int  len;
   char *string;
   bool isUtf;
};

在 32 位模式下将占用 12 个字节,但在 64 位模式下将占用 24 个字节。

struct list {
   char *string;
   int  len;
   bool isUtf;
};

在 32 位模式下将占用 12 个字节,但在 64 位模式下仅占用 16 个字节。

如果您有这些结构的数组,您的数据和代码大小都会增加 50%,因为以 2 的幂为索引比在其他大小上更简单。如果您的结构是单例或不频繁,则重新排序字段没有多大意义。如果用得很多,那就是看点。

至于你问题的另一点。为什么编译器不对字段进行这种重新排序,因为在这种情况下,很难实现使用通用模式的结构的联合。比如说。

struct header {
    enum type;
    int  len;
};

struct a {
    enum type;
    int  len;
    bool whatever1;
};

struct b {
    enum type;
    int  len;
    long whatever2;
    long whatever4;
};

struct c {
    enum type;
    int  len;
    float fl;
};


 union u {
    struct h header;
    struct a a;
    struct b b;
    struct c c;
 };

如果编译器重新排列字段,这种结构会更加不方便,因为typelen通过union. 如果我没记错的话,标准甚至要求这种行为。

于 2013-04-25T12:56:38.037 回答