2

我在 SO 中看到了很多关于对齐属性的问题,但是我没有在哪里找到优势或何时使用它(我的意思是我们必须在哪里以及在哪些场景中使用这个概念)。任何人都可以明确它的图片。刚刚从一个 SO 问题中复制了一个程序 一个用于对齐属性参考的程序

int main()
{
    结构数据
    {
        int a __attribute__( ( 对齐 ( 8 ) ) ) ;
        char ch __attribute__( ( 对齐 ( 1 ) ) ) ;
        float s __attribute__( ( 对齐 ( 4 ) ) ) ;    
    } ;
    结构数据 e ;
    printf ( "\n%u %u %u", &e.a, &e.ch, &e.s ) ;
    printf ( "\n%d", sizeof ( e ) ) ;
    返回 0 ;
}
4

2 回答 2

1

对齐的重要性主要体现在性能和可移植性上。如果您不了解您正在使用的平台的对齐要求,您的代码可能不一定能够在那里运行,或者一旦有人移动未正确对齐到该平台的代码(或数据),它就会中断。

根据硬件和操作系统等因素,其中一些会为您处理,但您会因制动对齐规则而受到一些惩罚。默认情况下,旧的 Windows 版本在发生对齐错误时会导致进程崩溃,今天 Windows 将能够恢复,但代价是额外的 CPU 周期。

对齐属性是强制对齐的 GCC 特定功能(它与 C 语言无关),对齐是您的数据必须在内存中布置的某个数字的倍数。然后,编译器将在您的数据结构中插入垃圾,以确保满足您对编译器施加的约束。

让我们以您的问题为例:

struct data
{
    int a    __attribute__( ( aligned ( 8 ) ) ) ;
    char ch  __attribute__( ( aligned ( 1 ) ) ) ;
    float s  __attribute__( ( aligned ( 4 ) ) ) ;
} ; 

我们假设在这种情况下intfloat我们假想平台上的原生大小都是 4 字节。

在内存中布局的最终​​结构将更接近

struct data
{
    int a;        // 0x00   
    int junk0     // 0x04
    char ch;      // 0x08
    char junk1[3] // 0x09
    float s;      // 0x0C
} ; 

我不确定编译器是否会填充第一个整数,以便它在最终结构中实际占用 8 个字节。仅仅因为填充,它不会是 64 位的,我觉得很奇怪,因为它会假设结构仅放置在 64 位地址上,所以在 32 位架构中,如果你分配内存,只有当内存对齐在一个 8 的倍数的地址是可以的。也许这是为了让它更便携,以确保它在 32 位和 64 位上的行为相同。

编译器可以选择更激进,实际上浪费更多空间,但是有包指令可以解决这个问题。如果本机二进制兼容性对您来说真的很重要,那么这些事情真的很重要。

于 2012-12-16T14:00:10.847 回答
1

第一个用例是当您有一个char用于存储其他内容的数组时,您需要将 allign 强制为正确的类型。

第二种情况是二进制协议,当您读取特定布局的数据(来自网络或文件)时,您需要使用对齐强制布局。

于 2012-12-16T13:51:09.733 回答