繁体   English   中英

C ++:使用没有位移的指针将unsigned char转换为unsigned int

[英]C++: Unsigned Char to unsigned int using pointers without bit shifts

假设我有一个类型为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);

假设我有一个指针偏移到一个开始4字节整数的位置:

// 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)));

简而言之,在C风格的字节数组中将四个字节转换为unsigned int的最干净,最有效的方法是什么?

正确的方法是使用memcpy:

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

在支持未对齐变量访问的体系结构(如x86-64)上,这将被优化为简单的指针取消引用,但在不支持未对齐访问的系统(例如ARM)上,它将正确地获取值出。

例如,请参阅: https//gcc.godbolt.org/z/l5Px4G 在gcc for x86和arm之间切换编译器,看看指令的不同之处。

如果您从某些外部源获取数据,请记住字节序的概念。 您可能必须翻转整数的字节以使值有意义。

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

在某些平台上,性能将是残酷的。 在某些平台上,代码会出错。

无论如何,转变和添加都非常清晰易懂。 演员阵容更加混乱,需要了解平台的字节顺序。 所以你不是让事情变得更好,更简单,也更清晰。

但是我不应该以某种方式使用演员表来做到这一点吗?

不,没有任何演员可以保证工作。


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

一个考虑因素是如何表示负数。 幸运的是,2的补充是如此无处不在的表现,我们通常可以忽略它。 但在你的情况下,由于你正在转换无符号整数,因此它更不重要。

更相关的考虑因素是字节字节序。

如果您知道该数组与执行该程序的CPU使用的表示相同,那么您可以使用std::memcpy复制字节:

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

只要源数据具有相同的表示形式,无论CPU使用的字节顺序如何,这都能正常工作。


你的建议(*(c+10) << 24) + ...是正确的(或者似乎是,我没有彻底检查)是否字节数组的表示是大端。 如果数组很少或有其他字节序,那么建议是错误的。

当通过网络接收数据时,此方法很有用,因为它不依赖于与执行CPU相同的表​​示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM