gpt4 book ai didi

c - GCC 的 __attribute__((__packed__)) 是否保留原始顺序?

转载 作者:太空狗 更新时间:2023-10-29 16:24:14 27 4
gpt4 key购买 nike

目的

我正在用 C(特别是 gnu89)编写一个网络程序,我想通过将某个 struct X 重新解释为大字节数组(又名 char),通过网络发送字节,并在另一端将它们重新解释为 struct X。为此,我决定使用 gcc 的 __attribute__((__packed__ ))。我已尽最大努力确保正确完成此操作(即我已考虑字节顺序和其他相关问题)。

问题

除了保证 struct X 尽可能小之外,gcc 是否保证用 __attribute__((__packed__ )) 定义的 struct 保留原始顺序?我进行了大量搜索,但尚未找到任何关于此保证是否存在的文档。

注意事项

可以安全地假设发送方和接收方都不会遇到可移植性问题(例如,服务器上的 sizeof(int) 等于服务器上的 sizeof(int)客户)。

最佳答案

是的,__attribute__((packed))(不需要第二组下划线)是实现二进制(即非文本)网络协议(protocol)的正确方法。元素之间不会有间隙。

但是你应该明白,packed 不仅打包结构,而且:

  • 使其所需的对齐为一个字节,并且
  • 确保其成员(可能因打包和结构本身缺乏对齐要求而错位)被正确读取和写入,即其字段的错位由编译器在软件中处理.

但是,如果您直接访问结构成员,编译器只会处理错位。您应该永远不要将指针指向压缩结构的成员(除非您知道该成员所需的对齐方式为 1,例如 char 或其他压缩结构)。以下 C 代码演示了该问题:

#include <stdio.h>
#include <inttypes.h>
#include <arpa/inet.h>

struct packet {
uint8_t x;
uint32_t y;
} __attribute__((packed));

int main ()
{
uint8_t bytes[5] = {1, 0, 0, 0, 2};
struct packet *p = (struct packet *)bytes;

// compiler handles misalignment because it knows that
// "struct packet" is packed
printf("y=%"PRIX32", ", ntohl(p->y));

// compiler does not handle misalignment - py does not inherit
// the packed attribute
uint32_t *py = &p->y;
printf("*py=%"PRIX32"\n", ntohl(*py));
return 0;
}

在 x86 系统(不强制内存访问对齐)上,这将产生

y=2, *py=2

如预期。另一方面,例如,在我的 ARM Linux 板上,它产生了看似错误的结果

y=2, *py=1

关于c - GCC 的 __attribute__((__packed__)) 是否保留原始顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1756811/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com