C中压缩属性的说明

时间:2016-07-28 11:37:29

标签: c compilation

我想知道是否有人可以对pset4中位图示例中使用的packed属性的含义提供更全面的解释。

  

"顺便提一下,我们对名为packed的属性的使用确保了clang不会尝试" word-align"成员(每个成员的第一个字节的地址是4的倍数),lest we end up with "gaps" in our structs that don’t actually exist on disk."

我不理解我们结构中差距的评论。这是指每个结构之间的内存位置中的间隙(即每个3字节RGB之间的一个字节,如果它是字 - algin)?为什么这对优化很重要?

typedef uint8_t BYTE;
typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

3 个答案:

答案 0 :(得分:2)

当心:展示偏见!

如注释中所述,当编译器将填充添加到结构时,它会这样做以提高性能。它使用了可以提供最佳性能的结构元素的对齐。

不久之前,DEC Alpha芯片将处理一个未对齐的内存请求' (umr)通过执行页面错误,跳转到内核,摆弄字节以获得所需的结果,并返回正确的结果。与正确对齐的内存请求相比,这非常缓慢;你不惜一切代价避免这种行为。

如果您未对齐内存访问,其他RISC芯片(用于)会给您一个SIGBUS错误。即便是英特尔芯片也必须采取一些花哨的步法来处理未对准的内存访问。

删除填充的目的是通过能够序列化和反序列化数据而不执行正确的工作来降低性能(但降低性能)。 - 这是一种懒惰的形式,当机器通信不是同一类型时实际上不能正常工作,所以应该首先进行正确的序列化。

我的意思是,如果您通过网络写入数据,通过将结构的内容写为内存块(省略错误检查等)来发送数据似乎更简单:

write(fd, &structure, sizeof(structure));

接收端可以读取数据:

read(fd, &structure, sizeof(structure));

但是,如果机器属于不同类型(例如,一个具有Intel CPU,另一个具有SPARC或Power CPU),则这两个机器中的数据解释将因两台机器的不同而异。数组是charchar数组。要可靠地中继信息,您必须就字节顺序达成一致(例如网络字节顺序 - 例如,这是TCP / IP网络中非常重要的因素),并且数据应按约定的顺序传输,以便结局可以理解对方在说什么。

您可以定义其他机制:您可以使用'发件人制作权利'机制,其中'接收器'让发件人知道它想要如何呈现数据,发件人负责修复传输的数据。您也可以使用'接收器制作正确的'相反的机制。这两个都已在商业上使用 - 请参阅DRDA一个此类协议。

鉴于BYTE的类型是uint8_t,在任何理智(商业上可行的)编译器中,结构中都不会有任何填充。国际海事组织,预防措施是一种幻想或恐惧症,没有现实基础。我当然需要一个经过仔细记录的反例来相信该属性有助于解决实际问题。

  

我被认为当你将整个结构传递给像fread这样的函数时,你可能会遇到问题,因为它假设你给它一个像大块内存的数组,没有任何空白。如果您的结构有间隙,则第一个字节最终会出现在正确的位置,但接下来的两个字节会写入间隙,而您没有正确的访问方式。

Sorta ...但大多数没有。问题是填充字节中的值是不确定的。但是,在所示的结构中,我遇到的任何编译器都没有填充;结构将是3个字节长。没有理由在结构内部(元素之间)或最后一个元素之后放置任何填充(并且标准禁止在第一个元素之前填充)。所以,在这种情况下,没有问题。

如果将二进制数据写入文件并且文件中有空洞,则可以在空洞处写入任意字节值。如果你回读相同(类型)的机器,实际上不会有问题。如果你回读一个不同的(类型)机器,可能会有问题 - 因此我对序列化和反序列化的评论。我只用了30多年的C语言编程;我从来不需要打包,也不要期待。 (是的,我使用标准布局处理序列化和反序列化 - 我主要使用的系统是使用大端数据传输,对应network byte order。)

答案 1 :(得分:1)

有时,结构的元素只是简单地与4字节边界(或者CPU中的寄存器大小)对齐,以优化对RAM的读/写访问。通常,较小的元素被打包在一起,但是对齐由结构中的较大类型决定。

在你的情况下,你可能不需要来打包结构,但它没有受到伤害。

对于一些编译器,结构中的每个字节最终可能占用4个字节的RAM 每个(因此,整个结构为12个字节)。打包struct会删除每个BYTE的对齐要求,并确保将整个struct放入一个4字节的DWORD中(除非整个程序的对齐设置为一个字节,或者struct是一个表示的数组)结构,在这种情况下,它实际上将存储在3个连续的RAM字节中。)

请参阅以下评论以进一步讨论......

答案 2 :(得分:-1)

目标就是你所说的,每个结构之间没有间隙。为什么这很重要?主要是因为缓存。内存访问速度慢!!!缓存非常快。如果你可以更多地适应缓存,你可以避免缓存未命中(内存访问)。

编辑:似乎我错了,如果目标是结构填充,那么似乎没有用,因为结构有3个BYTE