[英]Create a 64-bit result using different values
I have to create a 64byte value using val1
, val2
, val3
and val4
. 我必须使用
val1
, val2
, val3
和val4
创建一个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.