数据结构对齐

发布于 2024-08-10 17:18:33 字数 618 浏览 10 评论 0原文

因此,我正在编写一些数据包结构(以太网、IP 等),并注意到其中一些后面跟着 attribute((packed)),这会阻止 gcc 编译器尝试向它们添加填充。这是有道理的,因为这些结构应该连接到电线上。

但后来,我数了数:

struct ether_header
{
  u_int8_t  ether_dhost[ETH_ALEN];  /* destination eth addr */
  u_int8_t  ether_shost[ETH_ALEN];  /* source ether addr    */
  u_int16_t ether_type;             /* packet type ID field */
} __attribute__ ((packed));

这是从网站复制的,但我的代码也使用了2个uint8_t和1个uint16_t。这总共是两个字(4 个字节)。

根据源的不同,系统更喜欢根据 4,8 甚至 16 位的倍数来对齐结构。所以,我不明白为什么 attribute((packed)) 是必要的,因为据我所知,这不应该被打包。

另外,为什么双括号((打包))为什么不使用一对?

So, I'm coding some packet structures (Ethernet, IP, etc) and noticed that some of them are followed by attribute((packed)) which prevents the gcc compiler from attempting to add padding to them. This makes sense, because these structures are supposed to go onto the wire.

But then, I counted the words:

struct ether_header
{
  u_int8_t  ether_dhost[ETH_ALEN];  /* destination eth addr */
  u_int8_t  ether_shost[ETH_ALEN];  /* source ether addr    */
  u_int16_t ether_type;             /* packet type ID field */
} __attribute__ ((packed));

This is copied from a site, but my code also uses 2 uint8_t and 1 uint16_t. This adds up to two words (4 bytes).

Depending on the source, the system prefers that structures be aligned according to multiples of 4,8, or even 16 bits. So, I don't see why the attribute((packed)) is necessary, as afaik this shouldn't get packed.

Also, why the double brackets ((packed)) why not use one pair?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

柳絮泡泡 2024-08-17 17:18:33

如果您的结构已经是正确大小的倍数,那么不,__attribute__((packed)) 并不是绝对必要的,但它仍然是一个好主意,以防您的结构大小发生变化任何理由。如果您添加/删除字段,或更改 ETH_ALEN,您仍然需要 __attribute__((packed))

我相信需要双括号才能使您的代码与非 gcc 编译器兼容。通过使用它们,您可以执行以下操作:

#define __attribute__(x)

然后您指定的所有属性都将消失。额外的括号意味着只有一个参数传递给宏(而不是一个或多个),无论您指定多少个属性,并且您的编译器不需要支持可变参数宏。

If your structure is already a multiple of the right size, then no, the __attribute__((packed)) isn't strictly necessary, but it's still a good idea, in case your structure size ever changes for any reason. If you add/delete fields, or change ETH_ALEN, you'll still want __attribute__((packed)).

I believe the double parentheses are needed to make it easy to make your code compatible with non-gcc compilers. By using them, you can then just do this:

#define __attribute__(x)

And then all attributes that you specify will disappear. The extra parentheses mean there is only one argument passed to the macro (instead of one or more), regardless of how many attributes you specify, and your compiler does not need to support variadic macros.

热风软妹 2024-08-17 17:18:33

尽管您的系统可能更喜欢某些特定的对齐方式,但其他系统可能不喜欢。即使 __attribute__((packed)) 没有效果,这也是一种偏执。

至于为什么是双括号,这个GCC特有的扩展需要双括号。单括号将导致错误。

Although your system may prefer some specific alignment, other systems might not. Even if the __attribute__((packed)) has no effect, it's a good touch of paranoia.

As for why it's double-parenthesis, this GCC-specific extension requires double parenthesis. Single parenthesis will result in an error.

失而复得 2024-08-17 17:18:33
in win32, you can do like this: 
#pragma pack(push) //save current status 
#pragma pack(4)//set following as 4 aligned 
struct test 
{ 
char m1; 
double m4; 
int m3; 
}; 
#pragma pack(pop) //restore 
in win32, you can do like this: 
#pragma pack(push) //save current status 
#pragma pack(4)//set following as 4 aligned 
struct test 
{ 
char m1; 
double m4; 
int m3; 
}; 
#pragma pack(pop) //restore 
煞人兵器 2024-08-17 17:18:33

packed 指的是结构内部的填充/对齐,而不是结构的对齐。例如,

struct {
  char x;
  int y;
}

大多数编译器将在偏移量 4 处分配 y,除非您将结构声明为打包结构(在这种情况下,y 将在偏移量 1 处分配)。

packed refers to the padding/alignment inside the structure, not the alignment of the structure. For instance

struct {
  char x;
  int y;
}

Most compilers will allocate y at offset 4 unless you declare the struct as packed (in which case y will get allocated at an offset of 1).

孤君无依 2024-08-17 17:18:33

对于此结构,即使 ETH_ALEN 是奇数,也有两个,因此 uint16 变量必然位于两个或零字节偏移处,并且打包不会执行任何操作。对于可移植性来说,依赖 Packed 是一个坏主意,因为打包机制不可移植,如果您使用它们,您可能必须在成员变量中进行字节复制,以避免在重要的平台上出现未对齐异常。

For this structure, even if ETH_ALEN is an odd number, you have two of them, so the uint16 variable will neccessarily be at a two or zero byte offset, and the packed won't do anything. Depending on packed is a bad idea for portability, because the mechanism for packing aren't portable and if you use them you may have to byte copy in and out of your member variables to avoid misalignment exceptions on platforms that this matter for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文