C++ C++;:使用不带位移位的指针将无符号字符转换为无符号整数

C++ C++;:使用不带位移位的指针将无符号字符转换为无符号整数,c++,C++,假设我有一个类型为unsigned char的C样式数组: 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); 如果我想用正确的号码加载I,我可以执行以下操作: unsigned int i = (*(

假设我有一个类型为
unsigned char
的C样式数组:

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);
如果我想用正确的号码加载
I
,我可以执行以下操作:

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


简言之,在C型字节数组中,将四个字节转换为无符号整数的最干净、最有效的方法是什么。将非对象大小倍数的偏移量添加到指向已分配对象的指针可能会导致平台无法取消引用的指针。它根本不是指向
无符号int
的指针

在某些平台上,性能将非常糟糕。在某些平台上,代码会出错


在任何情况下,转移和添加都是非常清楚和容易理解的。强制转换更容易混淆,需要理解平台的字节顺序。因此,您没有使事情变得更好、更简单或更清晰。

正确的方法是使用memcpy:

unsigned int i;
std::memcpy(&i, c + offset, sizeof(unsigned int));
在支持未对齐变量访问的体系结构(如x86-64)上,这将优化为一个简单的指针解引用,但在不支持未对齐访问的系统(如ARM)上,它将正确地获取值

请参见示例:。在gcc for x86和arm之间切换编译器,并查看指令中的差异

如果您从外部来源获取数据,请记住endianness的概念。您可能需要翻转整数的字节才能使值有意义

但我不应该,不知何故,用石膏做这件事吗

// 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)));
不,没有一个演员能保证成功


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

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

一个更相关的考虑是字节结束

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

unsigned int i;
static_assert(sizeof i == 4);
std::memcpy(&i, c + 10, sizeof i);
只要源数据在相同的表示形式中,无论CPU使用的endianness是什么,它都能正常工作



你的建议
(*(c+10)
unsigned char*c
不是数组,它是指针。@bordeo——人们通常创建一个不指向任何地方的指针,并将其视为数组。区别很重要;当人们指出它时,不要生气。查看所有细节。这是一个观点。答案是什么?不同意。这一切都取决于这个字符是如何定义的已填充ffer。并且在平台上(x86_64)与标准的数据完全一样。就标准C++而言,这个答案是正确的。任何在某些平台上可能工作的问题都是基于未定义的行为或平台/编译器特定的保证。编辑:这个评论是指第一段。最后一段是一个意见。“将非对象大小倍数的偏移量添加到指向已分配对象的指针可能会导致平台无法取消引用的指针。"这是一个观点吗?让我们来看看。为什么在存在同样有效的平台独立选项的情况下,您会使用平台特定的代码?我的方法是平台特定的吗?
i
的值取决于表格的端点。@DavidSchwartz我们在您的回答中已经讨论过了。是否取决于它的问题无法回答不知道缓冲区最初是如何填充的。如果它是由同一个应用程序创建的,则不会。@PaulBelanger询问者受到了的阻碍。告诉他们他们不使用移位是愚蠢的,这没关系。啊,我可以直接记忆int指针?(假设我已经声明了int)如果问题显然有无符号整数,你为什么要关心符号?@SergeyA,因为我假设这个问题是一个更一般问题的简化版本。什么是
断言(sizeof I==4)
for?@NathanOliver问题的措辞,特别是每字节位移位实现,意味着4字节
int
。在一般情况下,此解决方案可能没有必要,但OP的情况显然取决于此。如果此解决方案是在不同的平台上以较大或较小的字节编译的,它将失败.
unsigned int i;
static_assert(sizeof i == 4);
std::memcpy(&i, c + 10, sizeof i);