2009-02-13 81 views
12

我想从char*数组中读取sizeof(int)个字节。从char *数组中读取“整数”大小的字节。

a)在什么情况下我们需要担心是否需要检查字节序?

b)如何读取前4个字节,或者考虑是否考虑字节顺序。

编辑:我已阅读的sizeof(int)字节需要与整数值进行比较。

什么是去了解这个问题的最好办法

+0

我对你想要做的事情有点困惑。你能写一些伪代码作为例子吗?你想从字符数组解析整数吗? – 2009-02-13 06:43:52

+0

我想从char *数组中找到sizeof(int)字节,并试图将它与一个整数进行比较。数据的来源是不同的机器。 – kal 2009-02-13 06:57:19

回答

1

你不应该需要担心endianess的,除非你正在阅读从不同的机器,例如上创建的源字节一个网络流。

鉴于这一点,你不能只使用for循环?

void ReadBytes(char * stream) { 
    for (int i = 0; i < sizeof(int); i++) { 
     char foo = stream[i]; 
     } 
    } 
} 

你在问什么比这更复杂的东西?

+0

我的数据实际上是从其他来源创建的 – kal 2009-02-13 06:55:37

1

只有当您正在阅读的数据由大于一个字节的数字组成时,您才需要担心字节数。
如果您正在阅读sizeof(int)字节并希望将它们解释为int,那么endianess会有所作为。基本上endianness是机器将一系列多于1个字节解释为数值的方式。

3

取决于你想如何阅读,我得到了你想要投4个字节转换成整数,这样通过网络流数据通常会在这样的事情结束了的感觉:

int foo = *(int*)(stream+offset_in_stream); 
+1

这可能会导致未对齐的访问。 – gimpf 2009-02-13 06:56:53

+0

@gimpf:我很好奇:在哪些系统上会导致错误? – Christoph 2009-02-13 11:15:45

+0

I.e.在80486和任何更好的CPU与对齐标志设置。 – 2009-02-13 15:48:29

18

待办事项你的意思是这样的?:

char* a; 
int i; 
memcpy(&i, a, sizeof(i)); 

你只需要担心如果字节序的数据的来源是不同的平台,就像一个设备。

1

只需使用for循环在sizeof(int)块中移动数组。
使用函数ntohl(至少在Linux上的标头<arpa/inet.h>中找到)将网络顺序中的字节(网络顺序定义为big-endian)转换为本地字节顺序。该库函数的实现可以为您运行的任何处理器执行正确的网络到主机转换。

9

a)如果数据是在big-endian机器上创建的,并且正在小端机器上处理,或者反过来,则只需要担心“字节顺序”(即字节交换)。有很多方法可以发生,但这里有几个例子。

  1. 您通过套接字在Windows机器上接收数据。 Windows采用小端架构,而网络数据“应该”采用大端格式。
  2. 您处理在具有不同“字节顺序”的系统上创建的数据文件。

无论在哪种情况下,都需要对所有大于1个字节的数字进行字节交换,例如,,短裤,整数,长裤,双打等等。但是,如果你总是在处理来自同一个平台的数据,那么endian问题就不成问题。

b)根据你的问题,这听起来像你有一个字符指针,并希望提取前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)); 
} 
3

最简单的办法来解决,这是确保任何生成字节一致的字节序这样做。通常,各种TCP/IP内容所使用的“网络字节顺序”最好是:库函数htonlntohl对此非常有效,它们的 通常相当优化。

但是,如果网络字节顺序未被使用,您可能需要以其他方式执行 。你需要知道两件事:一个整数的大小和字节顺序。 一旦你知道这一点,你就知道要提取多少个字节,并按照何种顺序将它们放在一起。

,它假定的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 
1

为什么阅读时,你可以比较?

bool AreEqual(int i, char *data) 
{ 
    return memcmp(&i, data, sizeof(int)) == 0; 
} 

如果您在需要将所有整数转换为某种不变形式时担心排序。 htonl和ntohl就是很好的例子。

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; 
}