我想从sizeof(int)
数组中读取char*
个字节。
a)在什么情况下我们需要担心是否需要检查字节顺序?
b)如何考虑或不考虑字节顺序,你将如何读取前4个字节。
编辑:我读过的sizeof(int)
字节需要与整数值进行比较。
解决此问题的最佳方法是什么
答案 0 :(得分:19)
你的意思是什么?:
char* a;
int i;
memcpy(&i, a, sizeof(i));
如果数据来源来自不同的平台,例如设备,则只需担心内联性。
答案 1 :(得分:9)
a)如果数据是在big-endian机器上创建的,并且正在小端机器上处理,反之亦然,你只需要担心“字节序”(即字节交换)。有很多方法可以实现,但这里有几个例子。
在上述任何一种情况下,您都需要对大于1个字节的所有数字进行字节交换,例如,short,int,long,double等。但是,如果您始终处理来自同一个数据的数据平台,端点问题无关紧要。
b)根据你的问题,听起来你有一个char指针,想要将前4个字节作为int提取,然后处理任何endian问题。要进行提取,请使用:
int n = *(reinterpret_cast<int *>(myArray)); // where myArray is your data
显然,这假设myArray不是空指针;否则,这将导致崩溃,因为它取消引用指针,因此采用一种良好的防御性编程方案。
要在Windows上交换字节,可以使用winsock2.h中定义的ntohs()/ ntohl()和/或htons()/ htonl()函数。或者您可以编写一些简单的例程来在C ++中执行此操作,例如:
inline unsigned short swap_16bit(unsigned short us)
{
return (unsigned short)(((us & 0xFF00) >> 8) |
((us & 0x00FF) << 8));
}
inline unsigned long swap_32bit(unsigned long ul)
{
return (unsigned long)(((ul & 0xFF000000) >> 24) |
((ul & 0x00FF0000) >> 8) |
((ul & 0x0000FF00) << 8) |
((ul & 0x000000FF) << 24));
}
答案 2 :(得分:3)
取决于你想如何阅读它们,我感觉你想把4个字节转换成一个整数,这样做通过网络流数据通常会以这样的方式结束:
int foo = *(int*)(stream+offset_in_stream);
答案 3 :(得分:3)
解决这个问题的简单方法是确保以一致的字节顺序生成字节。通常,各种TCP / IP内容使用的“网络字节顺序”是 最好:图书馆例程 htonl 和 ntohl 非常适合这个,他们 通常都是相当好的优化。
但是,如果未使用网络字节顺序,则可能需要执行操作 其他方法。您需要知道两件事:整数的大小和字节顺序。 一旦你知道了,就知道要提取多少字节以及放入哪个顺序 他们一起变成了一个int。
假设sizeof(int)的一些示例代码是正确的字节数:
#include <limits.h>
int bytes_to_int_big_endian(const char *bytes)
{
int i;
int result;
result = 0;
for (i = 0; i < sizeof(int); ++i)
result = (result << CHAR_BIT) + bytes[i];
return result;
}
int bytes_to_int_little_endian(const char *bytes)
{
int i;
int result;
result = 0;
for (i = 0; i < sizeof(int); ++i)
result += bytes[i] << (i * CHAR_BIT);
return result;
}
#ifdef TEST
#include <stdio.h>
int main(void)
{
const int correct = 0x01020304;
const char little[] = "\x04\x03\x02\x01";
const char big[] = "\x01\x02\x03\x04";
printf("correct: %0x\n", correct);
printf("from big-endian: %0x\n", bytes_to_int_big_endian(big));
printf("from-little-endian: %0x\n", bytes_to_int_little_endian(little));
return 0;
}
#endif
答案 4 :(得分:3)
怎么样
int int_from_bytes(const char * bytes, _Bool reverse)
{
if(!reverse)
return *(int *)(void *)bytes;
char tmp[sizeof(int)];
for(size_t i = sizeof(tmp); i--; ++bytes)
tmp[i] = *bytes;
return *(int *)(void *)tmp;
}
你会这样使用它:
int i = int_from_bytes(bytes, SYSTEM_ENDIANNESS != ARRAY_ENDIANNESS);
如果您使用的系统void *
int *
可能导致对齐冲突,则可以使用
int int_from_bytes(const char * bytes, _Bool reverse)
{
int tmp;
if(reverse)
{
for(size_t i = sizeof(tmp); i--; ++bytes)
((char *)&tmp)[i] = *bytes;
}
else memcpy(&tmp, bytes, sizeof(tmp));
return tmp;
}
答案 5 :(得分:1)
除非您从其他计算机上创建的源读取字节,否则您不必担心字节序。网络流。
鉴于此,你不能只使用for循环吗?
void ReadBytes(char * stream) {
for (int i = 0; i < sizeof(int); i++) {
char foo = stream[i];
}
}
}
你要求的东西比那更复杂吗?
答案 6 :(得分:1)
只有当您正在阅读的数据由大于一个字节的数字组成时,才需要担心字节顺序。
如果您正在读取sizeof(int)字节并期望将它们解释为int,则endianess会产生影响。实质上endianness是机器将一系列超过1个字节解释为数值的方式。
答案 7 :(得分:1)
只需使用在sizeof(int)块中移动数组的for循环
使用函数ntohl
(在标题<arpa/inet.h>
中找到,至少在Linux上)将网络顺序中的字节(网络顺序定义为big-endian)转换为本地字节顺序。该库函数用于为您运行的任何处理器执行正确的网络到主机转换。
答案 8 :(得分:1)
为什么要在比较时阅读?
bool AreEqual(int i, char *data)
{
return memcmp(&i, data, sizeof(int)) == 0;
}
当你需要将所有整数转换为某种不变形式时,如果你担心字节序。 htonl和ntohl是很好的例子。