Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 阅读「;整数;从char*数组中调整字节大小。_C++_C_Endianness - Fatal编程技术网

C++ 阅读「;整数;从char*数组中调整字节大小。

C++ 阅读「;整数;从char*数组中调整字节大小。,c++,c,endianness,C++,C,Endianness,我想从char*数组中读取sizeof(int)字节 a) 在什么情况下,我们需要担心是否需要检查endianness b) 您将如何读取前4个字节(是否考虑到endianness) 编辑:我读取的sizeof(int)字节需要与整数值进行比较 解决此问题的最佳方法是什么您不必担心endianess,除非您从另一台机器上创建的源读取字节,例如网络流 既然如此,就不能使用for循环吗 void ReadBytes(char * stream) { for (int i = 0; i <

我想从
char*
数组中读取
sizeof(int)
字节

a) 在什么情况下,我们需要担心是否需要检查endianness

b) 您将如何读取前4个字节(是否考虑到endianness)

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


解决此问题的最佳方法是什么

您不必担心endianess,除非您从另一台机器上创建的源读取字节,例如网络流

既然如此,就不能使用for循环吗

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

你要求的是比这更复杂的东西吗?

只有当你正在读取的数据是由大于一个字节的数字组成时,你才需要担心endianess。

如果您正在读取sizeof(int)字节,并希望将它们解释为int,那么endianess会有所不同。本质上是一台机器将一系列超过1字节的数据解释成一个数值的方式。

取决于您想如何读取它们,我感觉您想将4个字节转换成一个整数,通过网络传输的数据通常会以这样的方式结束:

int foo = *(int*)(stream+offset_in_stream);
int i = int_from_bytes(bytes, SYSTEM_ENDIANNESS != ARRAY_ENDIANNESS);

你的意思是这样的吗

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

如果数据源来自不同的平台(如设备),则只需担心endianess。

只需使用一个for循环,该循环以sizeof(int)块的形式在数组上移动。
使用函数
ntohl
(至少在Linux上可以在标题
中找到)将网络顺序中的字节(网络顺序定义为big-endian)转换为本地字节顺序。实现该库函数是为了对正在运行的任何处理器执行正确的网络到主机转换。

a)如果数据是在大端机器上创建的,而在小端机器上处理,则只需担心“端性”(即字节交换),反之亦然。有很多方法可以做到这一点,但这里有几个例子

  • 您通过套接字在Windows计算机上接收数据。Windows采用了一种小端结构,而网络数据“应该”是大端格式的
  • 处理在具有不同“endianness”的系统上创建的数据文件
  • 在这两种情况下,您都需要对所有大于1字节的数字进行字节交换,例如短、整数、长、双精度等。但是,如果您总是处理来自同一平台的数据,则不必担心endian问题

    b) 根据您的问题,听起来您有一个char指针,希望将前4个字节提取为int,然后处理任何endian问题。要进行提取,请使用以下命令:

    int n = *(reinterpret_cast<int *>(myArray)); // where myArray is your data
    
    int n=*(重新解释强制转换(myArray));//myArray是您的数据所在的位置
    
    显然,这假设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));
    }
    
    inlineunsignedshortswap_16位(unsignedshortus)
    {
    返回(无符号短)((us&0xFF00)>>8)|
    ((美国和0x00FF)>24)|
    ((ul&0x00FF0000)>>8)|
    
    ((ul&0x0000FF00)解决这个问题的简单方法是确保生成字节的内容以一致的结束方式进行。通常,各种TCP/IP内容使用的“网络字节顺序”是 最佳:库例程htonlntohl与此配合得非常好,并且 通常都是相当好的优化

    但是,如果未使用网络字节顺序,则可能需要在 你需要知道两件事:整数的大小和字节顺序。 一旦你知道了这一点,你就知道要提取多少字节以及按什么顺序放置 将它们合并为一个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
    
    #包括
    整数字节到整数大字节(常量字符*字节)
    {
    int i;
    int结果;
    结果=0;
    对于(i=0;i结果=(结果当你可以比较时,为什么要阅读

    bool AreEqual(int i, char *data)
    {
       return memcmp(&i, data, sizeof(int)) == 0;
    }
    
    如果您在需要将所有整数转换为某种不变形式时担心endianness,那么htonl和ntohl就是很好的例子。

    如何

    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 foo = *(int*)(stream+offset_in_stream);
    
    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;
    }
    

    我有点搞不清楚你想做什么。你能写一些伪代码吗,例如?你想从字符数组中解析整数吗?我想找到sizeof(int)从char*数组中提取字节并试图将其与整数进行比较。数据源是另一台计算机。我的数据实际上是从另一个源创建的,这可能会导致未对齐的访问。@gimpf:我很好奇:这会在哪些系统上导致错误?例如,在80486和任何设置了Align标志的更好的CPU上。什么时候是否设置对齐标志?在我的cpu上,这将导致总线错误。在sun处理器上(我相信SPARC),这也可能会失败。基本上,任何不支持未对齐读/写的处理器当然,这只适用于您实际从网络中读取内容的情况……好的,他在评论中说,他是从另一台机器上读取的。嗯,可能是通过刻录/读取CD来完成的,但更可能的是,他实际上指的是某种网络.u应该提到,第一个代码段与Daniels有相同的问题:它是ca