2014-05-24 62 views
2

我有一个uint8_t阵列,我需要从前面的4个元素,32位,创建一个size_tuint32_t在我的机器上)。从uint8_t数组的四个元素获取uint32_t的优雅方式?

实施例的非工作代码:

uint8_t array[8]; 
array[0] = 128; 
array[1] = 128; 
array[2] = 0; 
array[3] = 0; 
size_t size = array[0]; //results in 128 
size = *array; //also results in 128 

该数组的前四个指数的字节是80 80 00 00

我希望size_t通过读取该数组中最前面的4个字节(小端)来生成128 + 256 * 128。有没有办法使size_t初始化直接读取这4个字节,就好像该数组是任何旧的内存块,而不必手动添加和乘法以找到我想要的值?

回答

6

要以便携的方式(即独立于endian)使用shift操作符。像

uint32_t result = 0; 
for(int i=3; i>=0; --i) { 
    result <<= 8; 
    result += array[i]; 
} 
// result now holds the value you desire 
+0

我不知道任何有关这些转变经营者;这比我说的更好。这会导致机器进行数学运算,但似乎只会相当于复制数位。这会比做我建议的慢,但有一些编译器标志检测endianness? – sudo

+0

不要担心速度,直到(1)你已经证明你的代码太慢,并且(2)你已经证明即使开启了所有的优化。大多数编译器在优化这种事情方面做得很好。只需循环展开就可以解决这个问题,现代x86机器拥有各种各样的奇特操作码,仅用于这种类型的操作。 – dmckee

+0

我得到了两个基本相当的答案,都很好,但是这个更清洁一点,可扩展性更强,所以我会将其标记为答案。 – sudo

-1

明白了。当然,我问过之后!

uint32_t size = *((uint32_t*) array); 
+7

除了形成别名问题,我会警告你,如果在大vs-小的endian系统上使用相同的字节序列,* not *就会工作。 – WhozCraig

+0

@WhozCraig在什么情况下?如果一个big-endian机器使用例如'*((uint32_t *)array)= 8'写入,它也会读取*((uint32_t *)数组)作为8. – sudo

+0

@ 9000代码你在你的问题中写的不是独立于永久性。是的,双向投掷单向,然后其他方式在任何机器上都可以,但如果您打算对中间表示做任何事情,您需要知道机器如何处理整数表示。 – dmckee

2

东西这是正常的方式:

inline uint32 little_endian_to_uint32(uint8 *p) 
{ 
    return p[0] + p[1] * 0x100ul + p[2] * 0x10000ul + p[3] * 0x1000000ul; 
} 

你的编译器应该产生的最佳assmebly代码。

相关问题