简体   繁体   English

使用不同的值创建64位结果

[英]Create a 64-bit result using different values

I have to create a 64byte value using val1 , val2 , val3 and val4 . 我必须使用val1val2val3val4创建一个64byte的值。 Output should look like: 0xabcdabcd01000000 , but I am getting 0x81000000 输出应类似于: 0xabcdabcd01000000 ,但我得到的是0x81000000

uint32_t val1 = 0xabcdabcd;
uint8_t val2 = 1;
uint8_t val3 = 0;
uint16_t val4 = 0;
uint8_t final_val[8];
#define ADDR (&final_val[0])
//The output format is as follows: NNNNNNNNxyz
// NNNNNNNN: value1  in hex 
// x - val2, 
// y - val3, 
// z - val4  
int main() {

   uint64_t *ptr = (uint64_t *)ADDR ;
   *ptr = val1<<31|val2<<24|val3<<16|val4;
   printf("%p  0x%x \n", ptr, *ptr);
   return 0;

}

To create a 64-bit value: 要创建64位值:

1) Insure shifts are done with 64-bit operands when the result exceeds 32 bits. 1)当结果超过32位时,请确保使用64位操作数进行移位。

val1<<31    
(uint64_t) val1 << 31

2) Shift 32, not 31 bits to achieve the goal of NNNNNNNNxyz 2)移位32位而不是31位以实现NNNNNNNNxyz的目标

3) Avoid pointers tricks. 3)避免使用指针技巧。

uint8_t final_val[8];
// uint64_t *ptr = (uint64_t *)ADDR ;
uint64_t u64 = (uint64_t) val1 << 32 | val2 << 24 | val3 <<16 | val4;
memcpy(final_val, &u64, sizeof final_val);

4) Use matching printf specifiers. 4)使用匹配的printf说明符。

#include <inttypes.h>
//            v---- Not x, x is for unsigned
// printf("0x%x\n", u64);
printf("0x%" PRIx64 "\n", u64);
//           ^----^ from inttypes.h

Each of the shift terms except the first is evaluated as an int ; 除第一个移位项外的每个移位项被评估为一个int ; the first is evaluated as a uint32_t which is probably an unsigned int . 第一个被评估为uint32_t ,它可能是一个unsigned int These results are then or'd together in a uint32_t , and then assigned to your 64-bit result. 然后将这些结果放在uint32_t或在一起,然后分配给您的64位结果。

You need at least the first shift performed as a 64-bit calculation: 您至少需要将第一个移位作为64位计算来执行:

*ptr = (uint64_t)val1 << 32 | val2 << 24 | val3 << 16 | val4;

This can shift by 32 (as required, instead of 31 as before) because the shift is smaller than the size of the operand ( uint64_t ). 由于移位小于操作数( uint64_t )的大小,因此可以移位32(根据需要,而不是以前的31)。 Previously, you couldn't use 32 because you'd be told the shift is too big. 以前,您不能使用32,因为会被告知变化太大。

You might prefer the symmetry of: 您可能更喜欢对称性:

*ptr = (uint64_t)val1 << 32 | (uint64_t)val2 << 24 | (uint64_t)val3 << 16 | (uint64_t)val4;

Your printing is also faulty. 您的打印也有问题。 You should be using the macros from <inttypes.h> to specify the format for the uint64_t value: 您应该使用<inttypes.h>的宏来指定uint64_t值的格式:

printf("%p  0x%" PRIx64 "\n", ptr, *ptr);

Note that if you used unsigned long long *ptr etc, you'd use 0x%llx . 请注意,如果您使用unsigned long long *ptr等, 0x%llx使用0x%llx

The use of final_val is also dubious at best; 使用final_val也是可疑的。 it could crash on some machine types if final_val is not appropriately aligned for a 64-bit type (not aligned on a 64-bit boundary). 如果final_val未针对64位类型正确对齐(未在64位边界上对齐),则在某些计算机类型上可能会崩溃。 In the code shown, you should simply use a uint64_t variable to be the target of the pointer (since the code shown doesn't use final_val otherwise). 在显示的代码中,您应该简单地使用uint64_t变量作为指针的目标(因为显示的代码否则不使用final_val )。 If you did need to use the array of uint8_t values for some reason, then there are better ways to load the data. 如果由于某种原因确实需要使用uint8_t值数组,那么有更好的方法来加载数据。 You'd get different results on little-endian vs big-endian machines, too. 在little-endian和big-endian机器上,您也会得到不同的结果。

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

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