【发布时间】:2016-04-21 21:43:49
【问题描述】:
从字节流(文件、网络等)访问结构时 对齐是什么意思?
例如,我可以理解为什么编译器要填充以下内容 带有额外字节的结构,以在字地址(4 的倍数)处对齐 int a 和 short b。但是,这在访问内存时意味着什么? 通过使用指针的随机地址?使用 -> 运算符会生成低效的代码吗?还是我错过了什么?
typedef struct{
void* ptr; //4 bytes
char c1; //1 byte
int a; //4 bytes
char c2; //1 byte
short b; //2 byte
char c3; //1 byte
} Odd_Struct; //Minimum needed = 13 bytes, actual (with padding) = 20
unsigned char buffer[128];
Odd_Struct odd_struct;
odd_struct.a = 123456789;
odd_struct.b = 12345;
printf("sizeof(odd_struct): %d\n", sizeof(Odd_Struct));
memcpy(buffer+3, &odd_struct, sizeof(Odd_Struct));
Odd_Struct* testPtr = (Odd_Struct*)(buffer+3);
printf("testPtr->a: %d\n", testPtr->a);
printf("testPtr->b: %d\n", testPtr->b);
还有输出
sizeof(odd_struct): 20
testPtr->a: 123456789
testPtr->b: 12345
回答我为什么要这样做:
我打算使用内存非常有限的系统,所以很诱人 只需将一个字节(无符号字符)指针转换为结构指针并访问它 那样。无需额外的内存副本。 IE。使用到位的字节。 这在使用 gcc 的 x86 PC 上运行良好。但根据下面的 cmets,这似乎是个坏主意。
【问题讨论】:
-
C11 标准草案 n1570,6.3 转换,6.3.2.3 指针 7 指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未正确对齐引用类型,则行为未定义。[...]
-
在尝试对字段值使用读取或写入访问权限时,可能会出现总线错误。
-
不清楚你的意思。为什么(以及如何)会在对象的 contents 的来源处产生影响?如果您通过不同类型的指针访问一种类型的对象,则会调用未定义的行为。如果您是关于序列化,简单且唯一可移植的解决方案是使用带有 bitshift/bitops 的编组。
-
“如果结果指针未正确对齐引用类型,则行为未定义”因此,如果我没看错,不仅这段代码效率低下,而且根本不能保证工作?它在 gcc 中工作......为什么?它不适用于其他编译器/架构吗?
-
如果您提供更多上下文,我可以建议一些替代代码(例如,解释为什么要将此结构 memcpying 到 char 缓冲区中的随机位置)