C++ 从 char* 数组中读取“整数”大小的字节。
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/544928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading "integer" size bytes from a char* array.
提问by kal
I want to read sizeof(int)
bytes from a char*
array.
我想sizeof(int)
从char*
数组中读取字节。
a) In what scenario's do we need to worry if endianness needs to be checked?
a) 如果需要检查字节序,我们在什么情况下需要担心?
b) How would you read the first 4 bytes either taking endianness into consideration or not.
b) 无论是否考虑字节序,您将如何读取前 4 个字节。
EDIT :The sizeof(int)
bytes that I have read needs to be compared with an integer value.
编辑:sizeof(int)
我读取的字节需要与整数值进行比较。
What is the best approach to go about this problem
解决这个问题的最佳方法是什么
回答by Dani van der Meer
Do you mean something like that?:
你的意思是这样吗?:
char* a;
int i;
memcpy(&i, a, sizeof(i));
You only have to worry about endianess if the source of the data is from a different platform, like a device.
如果数据源来自不同的平台(如设备),您只需担心字节序。
回答by Matt Davis
a) You only need to worry about "endianness" (i.e., byte-swapping) if the data was created on a big-endian machine and is being processed on a little-endian machine, or vice versa. There are many ways this can occur, but here are a couple of examples.
a) 如果数据是在 big-endian 机器上创建并在 little-endian 机器上处理,您只需要担心“endianness”(即字节交换),反之亦然。发生这种情况的方式有很多,但这里有几个例子。
- You receive data on a Windows machine via a socket. Windows employs a little-endian architecture while network data is "supposed" to be in big-endian format.
- You process a data file that was created on a system with a different "endianness."
- 您通过套接字在 Windows 机器上接收数据。Windows 采用小端架构,而网络数据“应该”采用大端格式。
- 您处理在具有不同“字节序”的系统上创建的数据文件。
In either of these cases, you'll need to byte-swap all numbers that are bigger than 1 byte, e.g., shorts, ints, longs, doubles, etc. However, if you are always dealing with data from the same platform, endian issues are of no concern.
在这两种情况中的任何一种情况下,您都需要对所有大于 1 个字节的数字进行字节交换,例如,shorts、ints、longs、doubles 等。但是,如果您总是处理来自同一平台的数据,则字节序问题无关紧要。
b) Based on your question, it sounds like you have a char pointer and want to extract the first 4 bytes as an int and then deal with any endian issues. To do the extraction, use this:
b) 根据您的问题,听起来您有一个 char 指针,想要将前 4 个字节提取为 int,然后处理任何字节序问题。要进行提取,请使用以下命令:
int n = *(reinterpret_cast<int *>(myArray)); // where myArray is your data
Obviously, this assumes myArray is not a null pointer; otherwise, this will crash since it dereferences the pointer, so employ a good defensive programming scheme.
显然,这假设 myArray 不是空指针;否则,这将崩溃,因为它取消了指针的引用,因此请采用良好的防御性编程方案。
To swap the bytes on Windows, you can use the ntohs()/ntohl() and/or htons()/htonl() functions defined in winsock2.h. Or you can write some simple routines to do this in C++, for example:
要在 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));
}
回答by Matt Davis
The easy way to solve this is to make sure whatever generates the bytes does so in a consistent endianness. Typically the "network byte order" used by various TCP/IP stuff is best: the library routines htonland ntohlwork very well with this, and they are usually fairly well optimized.
解决这个问题的简单方法是确保生成字节的任何内容都以一致的字节顺序进行。通常,各种 TCP/IP 内容使用的“网络字节顺序”是最好的:库例程htonl和ntohl对此非常有效,并且它们通常得到了很好的优化。
However, if network byte order is not being used, you may need to do things in other ways. You need to know two things: the size of an integer, and the byte order. Once you know that, you know how many bytes to extract and in which order to put them together into an int.
但是,如果未使用网络字节顺序,则可能需要以其他方式进行处理。您需要知道两件事:整数的大小和字节顺序。一旦你知道了这一点,你就知道要提取多少字节以及将它们组合成一个 int 的顺序。
Some example code that assumes sizeof(int) is the right number of bytes:
一些假设 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
回答by Daniel Sloof
Depends on how you want to read them, I get the feeling you want to cast 4 bytes into an integer, doing so over network streamed data will usually end up in something like this:
取决于你想如何阅读它们,我觉得你想将 4 个字节转换为一个整数,通过网络流数据这样做通常会以这样的方式结束:
int foo = *(int*)(stream+offset_in_stream);
回答by Christoph
How about
怎么样
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;
}
You'd use it like this:
你会像这样使用它:
int i = int_from_bytes(bytes, SYSTEM_ENDIANNESS != ARRAY_ENDIANNESS);
If you're on a system where casting void *
to int *
may result in alignment conflicts, you can use
如果您使用的系统中的强制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;
}
回答by okutane
Why read when you can just compare?
当您可以进行比较时为什么要阅读?
bool AreEqual(int i, char *data)
{
return memcmp(&i, data, sizeof(int)) == 0;
}
If you are worrying about endianness when you need to convert all of integers to some invariant form. htonl and ntohl are good examples.
如果您在需要将所有整数转换为某种不变形式时担心字节顺序。htonl 和 ntohl 就是很好的例子。
回答by Steve Rowe
You shouldn't need to worry about endianess unless you are reading the bytes from a source created on a different machine, e.g. a network stream.
除非您从在不同机器上创建的源(例如网络流)读取字节,否则您无需担心字节序。
Given that, can't you just use a for loop?
鉴于此,您不能只使用 for 循环吗?
void ReadBytes(char * stream) {
for (int i = 0; i < sizeof(int); i++) {
char foo = stream[i];
}
}
}
Are you asking for something more complicated than that?
你要求的东西比这更复杂吗?
回答by shoosh
You need to worry about endianess only if the data you're reading is composed of numbers which are larger than one byte.
if you're reading sizeof(int) bytes and expect to interpret them as an int then endianess makes a difference. essentially endiannessis the way in which a machine interprets a series of more than 1 bytes into a numerical value.
仅当您正在读取的数据由大于一个字节的数字组成时,您才需要担心字节序。
如果您正在读取 sizeof(int) 字节并希望将它们解释为 int,那么字节序会有所不同。本质上,字节序是机器将一系列超过 1 个字节解释为数值的方式。
回答by Chris Connett
Just use a for loop that moves over the array in sizeof(int) chunks.
Use the function ntohl
(found in the header <arpa/inet.h>
, at least on Linux) to convert from bytes in the network order (network order is defined as big-endian) to local byte-order. That library function is implemented to perform the correct network-to-host conversion for whatever processor you're running on.
只需使用以 sizeof(int) 块在数组上移动的 for 循环。
使用函数ntohl
(在 header 中找到<arpa/inet.h>
,至少在 Linux 上)将网络顺序(网络顺序定义为 big-endian)中的字节转换为本地字节顺序。该库函数的实现是为了为您运行的任何处理器执行正确的网络到主机转换。