繁体   English   中英

如何从字节中生成十六进制数?

[英]How to make a hexadecimal number from bytes?

我想从单个字节组成数字0xAAEFCDAB 一切都顺利到 4 个四分体,并且由于某种原因额外增加了 4 个字节。 我究竟做错了什么?

#include <stdio.h>

int main(void) {
  unsigned long int a = 0;

  a = a | ((0xAB) << 0);
  printf("%lX\n", a);
  a = a | ((0xCD) << 8);
  printf("%lX\n", a);
  a = a | ((0xEF) << 16);
  printf("%lX\n", a);

  a = a | ((0xAA) << 24);
  printf("%lX\n", a);

  return 0;
}

Output:

图片

a = a | ((0xAA) << 24);

((0xAA) << 24)是一个负数(它是int ),然后将其符号扩展为 'unsigned long' 的大小,在开头添加那些0xffffffff

你需要告诉编译器你想要一个无符号数。

a = a | ((0xAAU) << 24);
int main(void) {
  unsigned long int a = 0;

  a = a | ((0xAB) << 0);
  printf("%lX\n", a);
  a = a | ((0xCD) << 8);
  printf("%lX\n", a);
  a = a | ((0xEF) << 16);
  printf("%lX\n", a);

  a = a | ((0xAAUL) << 24);

  printf("%lX\n", a);
  printf("%d\n", ((0xAA) << 24));

  return 0;
}

https://gcc.godbolt.org/z/fjv19bKGc

0xAA在位移期间按比例放大时被视为有符号值。 由于它的高位为 1 ( 0xAA = 10101010b ),因此在您移位之前将缩放值符号扩展0x...FFFFFFAA并将其ORa

您需要将0xAA转换为无符号值,然后再对其进行位移,因此它会被零扩展

C中的常量实际上是 typed ,一开始可能并不明显,常量的默认类型是一个int ,它是一个有符号的 32 位 integer (它取决于平台,但可能是您的情况)。

在有符号数字中,最高位描述数字的符号:1 为负数,0 为正数(有关更多详细信息,您可以阅读二进制补码)。

当您执行操作0xAB << 24时,它会产生一个 32 位有符号值0xAB000000 ,它等于二进制的10101011 00000000 00000000 00000000 如您所见,最高位设置为 1,这意味着整个 32 位有符号数实际上是负数。

为了执行| 64 位无符号数和 32 位有符号数之间a OR 运算,必须执行一些类型转换。 首先进行大小提升,根据二进制补码系统的规则,将0xAB000000的 32 位有符号值提升为0xFFFFFFFFAB000000的 64 位有符号值。 这是一个 64 位有符号数,其数值与转换前的 32 位有符号数相同。

之后,从 64 位有符号到 64 位无符号值执行类型转换,以便将值a . 这会用 1 填充最高位,并产生您在屏幕上看到的值。

为了强制您的常量与 32 位带符号的int类型不同,您可以使用ul等后缀,如我在答案开头链接的网站中所示。 在您的情况下, ul后缀应该效果最好,表示 64 位无符号值。 您的代码行与您a变量或常量看起来与此类似:

a = a | ((0xAAul) << 24);

暂无
暂无

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

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