将 char[] 转换为 C++ 中的结构时,计算机会忽略一个字节
Posted
技术标签:
【中文标题】将 char[] 转换为 C++ 中的结构时,计算机会忽略一个字节【英文标题】:A byte is ignored by the computer when casting a char[] to a struct in C++ 【发布时间】:2022-01-05 17:14:12 【问题描述】:我正在编写一个客户端-服务器程序,其中客户端是用 C++ 编写的,而服务器端是用 Python 编写的。
字节流从服务器端发送并接收到char[]
缓冲区,然后使用reinterpret_cast
转换为适当的结构。
char response_buffer[7];
recv(sock, response_buffer, 7, 0);
s_response* response = reinterpret_cast<s_response*>(response_buffer);
cout << response -> code << endl;
结构体是这样定义的:
typedef struct
unsigned char version;
unsigned short code;
unsigned int payload_size;
s_response;
但不是version
(1 字节) 得到response_buffer[0]
中的值,而code
得到response_buffer[1]
和response_buffer[2]
(两个字节 ),code
最终得到response_buffer[2]
和response_buffer[3]
中的值,而payload_size
得到response_buffer[4]
到response_buffer[6]
,因此,值response_buffer[1]
不会插入到任何结构的属性中,并且结果是一团糟。
起初,我认为这是由于字节顺序,但是当我发送值 2、2001 和 13821 时,例如,从服务器端来看,response_buffer
中的值如下:
0. 00000010
1. 11101001
2. 00000011
3. 11111101
4. 00110101
5. 00000000
6. 00000000
这是我期望得到的,并且顺序正确。但是当我打印出response->code
时,我得到的值是64771
,它是11111101 00000011
(上面列表中的2 和3),而不是2001
,它是00000011 11101001
(列表中的1 和2)。意思是,当我将char*
转换为s_response*
时,response_buffer
中位置 1 的字节将被忽略,并且从那里开始的值从正确的顺序偏移了一个字节。
知道我做错了什么吗?
【问题讨论】:
此问题显示的代码不符合 *** 显示 minimal reproducible example 的要求。因此,这里的任何人都不太可能最终回答这个问题。但最多只能猜测。你需要edit你的问题来展示一个最小的例子,不超过一两页代码(“最小”部分),其他人都可以剪切/粘贴完全如图所示,编译、运行和重现所描述的问题(“可重现”部分,这包括任何辅助信息,如程序的任何输入)。请参阅How to Ask 了解更多信息。 另外,如果您尝试查看sizeof
的结构是什么,您可能会感到惊讶,并自己找出答案。
char response_buffer[7];
可能不够大,无法容纳s_response
类型的对象(由于结构填充) - 您应该改用char response_buffer[sizeof(s_response)];
reinterpret_cast<s_response*>(response_buffer)
看起来像 UB。
如果你使用 TCP,你需要检查你收到了多少,只有当你得到足够的时候才能解析数据。
【参考方案1】:
正如 cmets 中所写,是结构填充造成了问题。
如下图添加#pragma
s即可解决
#pragma pack(push,1)
typedef struct
unsigned char version;
unsigned short code;
unsigned int payload_size;
s_response;
#pragma pack(pop)
【讨论】:
以上是关于将 char[] 转换为 C++ 中的结构时,计算机会忽略一个字节的主要内容,如果未能解决你的问题,请参考以下文章
C++ 编译时提示:不能将参数 1 从“char [6]”转换为“LPCTSTR”
C++ 我将一个const char*的字符串转换为string出错
在 C++ 中使用 atoi 将 char 数组转换为 int 值