This question on SO主要从严格别名规则的角度处理char
<-> uint8_t
问题。粗略地说,它阐明了只要将uint8_t
实现为char
或unsigned char
,我们就可以了。
我想了解使用uint8_t
时char
与reinterpret_cast
的有符号/无符号性可能不兼容的问题。
当我需要直接处理字节时,我更喜欢使用uint8_t
。但是,Winsock API处理char*
。
我想了解如何正确处理这些转换,以免发生 undefined 行为或其他损害应用程序可移植性的现象。
以下函数采用std::array<uint8_t, 4>
并将其转换为uint32_t
-即,采用4个字节并将其转换为整数。
uint32_t bytes_to_u32(const std::array<uint8_t, 4>& bytes) {
return (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
}
但是,从套接字传入的数据(使用recv
函数)以char*
形式出现。一种方法如下:
std::array<uint8_t, 4> length_buffer;
int bytes_received = 0;
while (bytes_received < 4) {
bytes_received += recv(sock, reinterpret_cast<char*>(length_buffer.data()) + bytes_received, 4 - bytes_received, 0);
}
它似乎可以在我的机器上运行。但是-这样安全吗?如果我没记错的话,在另一台机器或编译器上,char
可能是signed
,这意味着转换后length_buffer
将持有错误的值。我错了吗?我知道
reinterpret_cast
根本不改变位模式-它使二进制数据保持不变。知道了这一点,无论这项技术是否正确,它仍未完全融入我的大脑。请说明如何解决此问题。
编辑:另外请注意,将
char*
转换为uint8_t*
之后,我需要能够将uint8_t*
转换为有效的数值,或者有时测试缓冲区中各个字节的数值。为了解释“命令”,我是通过网络发送的,然后将其发送回另一端。
最佳答案
我希望我确实正确理解了您的问题,您可以使用联合来解决此问题:
//Union is template so you can use this for any given type
template<typename T>
union ConvertBytes
{
T value;
char byte[sizeof(T)];
};
void process()
{
recv(socket, buffer, bufferLength, 0); //Recieve data
ConvertBytes<uint32_t> converter;
for (int i = 0; i < sizeof(uint32_t); i++) //Considering that you recieve only that one uint32
{
converter.byte[i] = buffer[i]; //Assign all bytes into union
}
uint32_t result = converter.value; //Get uint32_t value from union
}
关于c++ - 将传入网络 `char*`数据转换为 `uint8_t`并返回的安全方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62499439/