“#pragma pack”和“__attribute __((aligned))”之间的区别是什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“#pragma pack”和“__attribute __((aligned))”之间的区别是什么?相关的知识,希望对你有一定的参考价值。

#pragma pack(L1_CACHE_LINE)
struct A {
  //...
};
#pragma pack()

A a;

struct A {
  //...
};

A a __attritube__((aligned(L1_CACHE_LINE)))

他们之间有什么区别?

答案

#pragma pack(字节对齐)影响结构的每个成员,由字节对齐输入或其自然对齐边界指定,以较小者为准。

__attribute__((aligned(byte-alignment)))影响变量的最小对齐(如果在struct中指定,则为struct字段)

我相信以下是相同的

#define L1_CACHE_LINE 2

struct A
{
    u_int32_t   a   __attribute__ ( (aligned(L1_CACHE_LINE)) );
    u_int32_t   b   __attribute__ ( (aligned(L1_CACHE_LINE)) );
    u_int16_t   c   __attribute__ ( (aligned(L1_CACHE_LINE)) );       
    u_int16_t   d   __attribute__ ( (aligned(L1_CACHE_LINE)) );      
    u_int32_t   e   __attribute__ ( (aligned(L1_CACHE_LINE)) );     
};


#pragma pack(L1_CACHE_LINE)
struct A
{
    u_int32_t   a;  
    u_int32_t   b;  
    u_int16_t   c;  
    u_int16_t   d;  
    u_int32_t   e;  
};
#pragma pack()

在哪里是一个qazxsw poi将确保qazxsw poi内的qazxsw poi将与2字节对齐,但不会以相同的方式对齐另一个变量。

参考:

  1. a __attritube__((aligned(L1_CACHE_LINE)))
  2. u_int32_t a
另一答案

struct A是一种Microsoft语法,出于兼容性原因而一直是http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Fcompiler%2Fref%2Frnpgpack.htm

http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/attributes-variables.html是一种特定于GCC的语法(MSVC不支持)。

以下是差异的摘要:

  • #pragma pack(和变体)更简洁,在GCC语法中表示属性ported to GCC__attribute__((aligned))(参见下面的示例);
  • #pragma pack适用于插入之后放置的每个结构定义(或直到另一个packed覆盖它),而GCC aligneds在本地定义为一种类型;
  • #pragma pack不如属性细粒度:它不能仅应用于结构的少数成员。然而,在实践中,这很少是一个问题,因为您很少需要对同一结构的成员进行不同的对齐和打包设置。

以非常简洁的方式,#pragma pack大致相当于__attribute__:它定义了包装(用于节省内存的压缩结构)和最小对齐。因此pragxswpoi(最小对齐)在pragma上。

原则上,#pragma pack可以使用GCC属性进行模拟,但不能相反,因为属性给出了更精细的控制。

以下是您可以在GCC上测试的示例:第一个定义使用#pragma pack(n),第二个定义使用属性。两种情况下的布局都是相同的。

__attribute__((packed,aligned(n)))

海湾合作委员会在这个例子上发出警告:n。实际上,更简洁和恰当的解决方案是将#pragma pack应用于整个结构(如@Hagai所做的那样),这是等效的1。但请注意,您不能简单地将#pragma pack应用于整个结构:行为不等于将#include <stdio.h> #include <stddef.h> // for offsetof() #pragma pack(push, 4) struct st { char c; double d; short e; }; #pragma pack(pop) // disables the effect of #pragma pack from now on struct st2 { char c __attribute__((packed,aligned(4))); double d __attribute__((packed,aligned(4))); short e __attribute__((packed,aligned(4))); }; void main() { printf("offsetof(struct st, d) = %zu ", offsetof(struct st, d)); printf("offsetof(struct st2, d) = %zu ", offsetof(struct st2, d)); printf("offsetof(struct st, e) = %zu ", offsetof(struct st, e)); printf("offsetof(struct st2, e) = %zu ", offsetof(struct st2, e)); } 分别应用于每个字段。

请注意,如果在同一结构定义中组合两个(pragma +属性),则算法更复杂,因为它必须遵守几个约束,这导致在(1)‘packed’ attribute ignored for field of type ‘char’给出的对齐之间进行一些packed / aligned计算, (2)成员类型的最小对齐,以及(3)在字段中声明的aligned属性(如果有的话)。

1来自min

为struct和union类型指定packed属性等效于在每个结构或union成员上指定packed属性。

以上是关于“#pragma pack”和“__attribute __((aligned))”之间的区别是什么?的主要内容,如果未能解决你的问题,请参考以下文章

#pragma pack()

#pragma pack(n)

#pragma pack(n)

#pragma pack (n) 设置对齐方式

关于结构体内存对齐方式的总结(#pragma pack()和alignas())

“#pragma pack”和“__attribute __((aligned))”之间的区别是什么?