我正在尝试将结构转换为char数组以通过网络发送.但是,当我这样做时,我从char数组得到了一些奇怪的输出.
#includestruct x { int x; } __attribute__((packed)); int main() { struct x a; a.x=127; char *b = (char *)&a; int i; for (i=0; i<4; i++) printf("%02x ", b[i]); printf("\n"); for (i=0; i<4; i++) printf("%d ", b[i]); printf("\n"); return 0; }
这是ax的各种值的输出(在使用gcc的X86上):
127:
7f 00 00 00
127 0 0 0
128:
ffffff80 00 00 00
-128 0 0 0
255:
ffffffff 00 00 00
-1 0 0 0
256:
00 01 00 00
0 1 0 0
我理解127和256的值,但为什么数字在转到128时会改变?为什么不会这样:80 00 00 00 128 0 0 0
我忘了在转换过程中做某些事情,还是忘记了整数表示?
*注意:这只是一个小测试程序.在一个真正的程序中,我在结构中有更多,更好的变量名,我转换为little-endian.
*编辑:格式化
你看到的是保持从char转换为int的符号.该行为是由于在您的系统上char已签名(注意: char未在所有系统上签名).如果位模式产生char的负值,那将导致负值.将这样的char提升为int将保留符号,而int也将是负数.请注意,即使您没有(int)
显式放置,编译器也会在传递给printf时自动将字符提升为int.解决方案是将您的值转换为unsigned char
第一个:
for (i=0; i<4; i++) printf("%02x ", (unsigned char)b[i]);
或者,您可以unsigned char*
从一开始就使用:
unsigned char *b = (unsigned char *)&a;
然后在使用printf打印时不需要任何演员表.
char是签名类型; 所以使用二进制补码,对于一个8位整数(即一个字节),0x80为-128
在x
本身的格式说明表示,该说法是int
,由于是负数,printf
需要8个字符显示的所有四个非零字节int
尺度的价值.该0
修饰符告诉垫用零输出,以及2
修改表示,最小输出应该是两个字符长.据我所知,除了字符串之外,printf
没有提供指定最大宽度的方法.
现在,你只传递一个char
,所以裸x
告诉函数使用int
传递的全部- 因为" ...
"参数的默认参数提升.尝试使用hh
修饰符来告诉函数将参数视为一个char
而不是:
printf("%02hhx", b[i]);
将结构视为char数组是未定义的行为.要通过网络发送,请使用正确的序列化.这是C++的痛苦,在C中更是如此,但它是您的应用程序独立于机器读写的唯一方式.
http://en.wikipedia.org/wiki/Serialization#C