我正在尝试将结构转换为char数组以通过网络发送。但是,当我这样做时,我从char数组得到了一些奇怪的输出。
#include <stdio.h>
struct 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;
}
这是a.x的各种值的输出(在使用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。
*编辑:格式化
答案 0 :(得分:11)
您看到的是保留从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打印时不需要任何演员表。
答案 1 :(得分:8)
char是签名类型;因此,对于2位补码,对于8位整数(即一个字节),0x80为-128
答案 2 :(得分:8)
x
格式说明符本身表示该参数为int
,并且由于该数字为负数,printf
需要八个字符才能显示所有四个非零字节int
- 大小的值。 0
修饰符告诉用零填充输出,2
修饰符表示 minimum 输出应该是两个字符长。据我所知,printf
没有提供指定最大宽度的方法,除了字符串。
现在,您只传递char
,因此裸x
告诉函数使用已传递的完整int
- 由于默认参数提升为“{ {1}}“参数。尝试...
修饰符告诉函数将参数视为hh
而不是:
char
答案 3 :(得分:5)
将结构视为char数组是未定义的行为。要通过网络发送,请使用正确的序列化。这是C ++的痛苦,在C中更是如此,但它是你的应用程序独立于机器读写的唯一方式。
答案 4 :(得分:2)
将您的结构转换为字符或字节,就像您尝试使其网络中立一样。为什么不现在解决这个问题呢?您可以使用各种不同的技术,所有这些技术都可能比您尝试的更“便携”。例如:
htonl
,htons
,ntohl
和{一直在处理以机器中立的方式在网络上发送数字数据{1}}。例如,请参阅FreeBSD或Linux系统上的byteorder(3)手册页。答案 5 :(得分:1)
char是一个签名类型,所以你看到的是两个赞美表示,转换为(unsigned char *)将解决这个问题(Rowland只是打败了我)。
在旁注中您可能想要更改
for (i=0; i<4; i++) {
//...
}
到
for (i=0; i<sizeof(x); i++) {
//...
}
答案 6 :(得分:1)
char数组的签名不是问题的根源! (这是问题,但不是唯一的问题。)
对齐!这是关键词。这就是为什么你永远不应该尝试像原始记忆一样对待结构。编译器(和各种优化标志),操作系统和月亮阶段都对结构中“相邻”字段的存储器中的实际位置做了奇怪和令人兴奋的事情。例如,如果你有一个带有char后跟一个int的结构,整个结构将是内存中的EIGHT字节 - char,3个空白,无用的字节,然后是int的4个字节。机器喜欢做这样的事情,所以结构可以很好地适应内存页面,例如。
在当地大学学习机械架构的入门课程。同时,正确序列化。永远不要像char数组那样处理结构。
答案 7 :(得分:1)
当你去发送它时,只需使用:
(字符*)及CustomPacket
转换。适合我。
答案 8 :(得分:0)
您可能希望转换为unsigned char数组。
答案 9 :(得分:-1)