我编写了一个小程序来向您展示铸造问题
#include <stdlib.h>
struct flags {
u_char flag1;
u_char flag2;
u_short flag3;
u_char flag4;
u_short flag5;
u_char flag7[5];
};
int main(){
char buffer[] = "\x01\x02\x04\x03\x05\x07\x06\xff\xff\xff\xff\xff";
struct flags *flag;
flag = (struct flags *) buffer;
return 0;
}
我的问题是当我强制转换标志5时,错误地取“\ x06 \ xff”字节忽略“\ x07”而标志7错误地接受下一个4“\ xff”字节加上一个nul,这是下一个字节我也运行gdb
(gdb) p/x flag->flag5
$1 = 0xff06
(gdb) p/x flag->flag7
$2 = {0xff, 0xff, 0xff, 0xff, 0x0}
(gdb) x/15xb flag
0xbffff53f: 0x01 0x02 0x04 0x03 0x05 0x07 0x06 0xff
0xbffff547: 0xff 0xff 0xff 0xff 0x00 0x00 0x8a
为什么会发生这种情况以及我如何才能正确处理? 感谢
答案 0 :(得分:3)
看起来像结构成员对齐问题。除非您知道编译器如何打包结构成员,否则不应该假设这些成员在内存中的位置。
0x07明显丢失的原因是因为编译器可能正在对16位边界上的flag5成员进行对齐,跳过保存0x07值的奇数内存位置。该值在填充中丢失。此外,你正在做的是溢出缓冲区,一个很大的禁忌。换句话说:
struct flags {
u_char flag1; // 0x01
u_char flag2; // 0x02
u_short flag3; // 0x04 0x03
u_char flag4; // 0x05
// 0x07 is in the padding
u_short flag5; // 0x06 0xff
u_char flag7[5]; // 0xff 0xff 0xff 0xff ... oops, buffer overrun, because your
// buffer was less than the sizeof(flags)
};
您通常可以使用大多数编译器控制结构成员的打包,但该机制是特定于编译器的。
答案 1 :(得分:2)
编译器可以自由地在结构的成员之间放置一些未使用的填充(例如)将对齐安排到它的会议中。您的编译器可能会提供#pragma packed
或命令行参数,以确保紧密的结构打包。
答案 2 :(得分:0)
如何存储结构是实现定义的,因此,您不能依赖特定的内存布局来进行序列化。
要将结构序列化为字节数组,请编写一个按设定顺序序列化每个字段的函数。
答案 3 :(得分:0)
您可能需要pack the struct:
struct flags __attribute__ ((__packed__)) {
u_char flag1;
u_char flag2;
u_short flag3;
u_char flag4;
u_short flag5;
u_char flag7[5];
};
注意:这是GCC - 我不知道它有多便携。
答案 4 :(得分:0)
这与填充有关。编译器正在为您的struct添加垃圾内存,以使其与您的内存正确对齐以提高效率。
请参阅以下示例:
http://msdn.microsoft.com/en-us/library/71kf49f1(v=vs.80).aspx
http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86