25 c compiler-construction networking gcc struct
目的
我正在用C语言编写一个网络程序(特别是gnu89),我希望通过重新解释一个特定的struct X大字节数组(也就是说char),通过网络发送字节,并struct X在另一方面重新解释它们来简化事情.为此我决定使用gcc的__attribute __((__ packed__)).我已尽最大努力确保正确完成(即我已经考虑了字节序和其他相关问题).
题
除了保证struct X尽可能小,gcc是否保证struct使用__attribute __((__ packed__))定义的保留原始排序?我已经做了相当多的搜索,我还没有找到关于这种保证是否存在的任何文件.
笔记
可以安全地假设发送方和接收方都不会遇到可移植性问题(例如sizeof(int),在服务器上等于sizeof(int)客户端).
Amb*_*jak 39
是的,__attribute__((packed))(不需要第二组下划线)是实现二进制(即非文本)网络协议的正确方法.元素之间不会有差距.
但是你应该明白,packed不仅包装结构,而且:
但是,如果直接访问struct成员,编译器将只处理错位.您永远不应该指向打包结构的成员(除非您知道成员的必需对齐为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;
}
Run Code Online (Sandbox Code Playgroud)
在x86系统上(不强制执行内存访问对齐),这将产生
y=2, *py=2
Run Code Online (Sandbox Code Playgroud)
正如所料.另一方面,在我的ARM Linux板上,它产生了看似错误的结果
y=2, *py=1
Run Code Online (Sandbox Code Playgroud)
Rob*_*ble 27
假设您正在询问结构成员是否将保留其定义中指定的顺序,答案是肯定的.标准要求后续成员的地址越来越多:
第§6.7.2.1p13节:
在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.
并且packed属性的文档清楚地表明只有填充/对齐受到影响:
packed属性指定变量或结构字段应具有最小可能的对齐 - 变量的一个字节和字段的一个位,除非您使用aligned属性指定更大的值.