代码之家  ›  专栏  ›  技术社区  ›  Chris

C++:使用无位错指针的无符号char到无符号int

c++
  •  3
  • Chris  · 技术社区  · 6 年前

    假设我有一个类型为 unsigned char :

    unsigned char * c = (unsigned char *) malloc(5000 * sizeof(unsigned char));
    for(int i = 0; i < 5000; i++) 
        c[i] = (unsigned char) ((i >> (i%4 * 8)) & 0xFF);
    

    // pseudo code
    unsigned int i = c + 10; // 10 = pointer offset, let's say. 
    

    如果我想加载 i 找到正确的号码,我可以做:

    unsigned int i = (*(c+10) << 24) + (*(c+11) << 16) + (*(c+12) << 8) + (*(c+13));
    

    但我不应该,不知何故,用石膏做这个吗?

    // pseudo code -- I haven't gotten this to work yet: 
    
    int i = (unsigned int) (*((void *)(c+10));
    
    // or maybe
    int i = *((unsigned int*)((void *)(c+10)));
    

    简而言之,将四个字节转换为 unsigned int 在C型字节数组中?

    3 回复  |  直到 6 年前
        1
  •  6
  •   Paul Belanger    6 年前

    正确的方法是使用memcpy:

    unsigned int i;
    std::memcpy(&i, c + offset, sizeof(unsigned int));
    

    参见示例: https://gcc.godbolt.org/z/l5Px4G . 在gcc for x86和arm之间切换编译器,并查看指令中的差异。

        2
  •  3
  •   David Schwartz    6 年前

    不,你不应该。将非对象大小倍数的偏移量添加到指向已分配对象的指针中,可能会导致平台无法取消引用的指针。很简单 unsigned int

    无论如何,移位和加法都是非常清楚和容易理解的。强制转换比较混乱,需要理解平台的字节顺序。所以你没有让事情变得更好,更简单,更清晰。

        3
  •  3
  •   eerorika    6 年前

    但我不应该,不知何故,用石膏做这个吗?

    不,没有哪个演员能保证成功。


    请注意,整数有许多表示形式。如何将字节数组转换为整数对象取决于整数在数组中的表示方式。例如,如果整数转换为字节数组并通过网络发送,则无法知道接收计算机是否使用相同的表示形式。

    一个需要考虑的问题是如何表示负数。幸运的是,2的补码是如此普遍的表示,我们通常可以忽略这一点。不过,在您的例子中,这更不重要,因为您要转换一个无符号整数。

    一个更相关的考虑是字节终结性。

    如果知道数组与执行程序的CPU使用的表示形式相同,那么可以使用 std::memcpy :

    unsigned int i;
    static_assert(sizeof i == 4);
    std::memcpy(&i, c + 10, sizeof i);
    

    只要源数据在相同的表示形式中,无论CPU使用的endianness是什么,这都可以正常工作。


    你的建议 (*(c+10) << 24) + ...

    这种方法在通过网络接收数据时非常有用,因为它不依赖于与执行CPU相同的表示。