【问题标题】:Storing hexadecimal number in char在char中存储十六进制数
【发布时间】:2013-07-15 17:15:55
【问题描述】:
#include <stdio.h>

int main(int argc, char const *argv[])
{
  char  a = 0xAA;
  int b;

  b = (int)a;
  b = b >> 4;

  printf("%x\n", b);
  return 0;
}

这里的输出是fffffffa。谁能给我解释一下这个输出是怎么得到的?

【问题讨论】:

  • 可能是签名字符,这可能对unsigned char a=0xAA;有帮助
  • 请注意,没有“十六进制数”之类的东西。相反,您可能拥有“数字的十六进制表示”,就像您可能拥有相同数字的十进制或二进制表示一样。一个数字就是一个数字——它没有底。
  • @HotLicks Heh... 当然,您可以用“没有数字这样的东西”来跟进 - “数字”只是人类提出的有助于逻辑思考的心理结构关于东西,如果确实有“逻辑”之类的东西......;-P
  • @twalberg - 我不确定我是否明白其中的逻辑。 ;-P

标签: c


【解决方案1】:

C 标准允许编译器设计者选择char 是有符号还是无符号。您的系统似乎使用签名的 chars 和 32 位 ints。由于设置了0xAA(二进制10101010)的最高有效位,该值被符号扩展为0xFFFFFFAA

将有符号值右移也会对结果进行符号扩展,因此当您移出低四位时,四个 1 从左移入,最终输出为 0xFFFFFFFA

编辑:根据 C99 规范,十六进制整数常量(例如您的示例中的 0xAA)根据其长度被视为不同长度的 ints。因此,将 0xAA 分配给带符号的 char 超出范围:分配值的正确方法是使用十六进制字符文字,如下所示:

char a='\xAA';

【讨论】:

  • 你确定没有签名溢出吗?:stackoverflow.com/questions/13569566/…
  • @ShafikYaghmour 我很确定右移永远不会导致溢出 - 这是一个符号扩展场景。但是,左移很容易导致溢出...
  • 好吧,如果它是一个有符号字符,他将一个超出范围的值分配给a,这是未定义的行为。
  • @ShafikYaghmour 好问题! 0xAAint,而不是 char。如果他用'\xAA',我肯定不是char溢出;我需要检查标准才能确定。
  • @ShafikYaghmour 哦,那个溢出了......(我想我应该检查一下链接)。是的,从标准的角度来看,这可能是未定义的。但大多数实现可能会认为char a=0xaa 等同于char a=-86...
【解决方案2】:

当您将 0xAA 放入到 0xFFFFFFAA 的 int 中时,它看起来像扩展了符号。然后,当您将其右移四位(一个十六进制字符)时,您最终得到 0xFFFFFFFA。

  //a is 8-bits wide.  If you interpret this as a signed value, it's negative
  char a=0xAA;

  int b; //b is 32 bits wide here, also signed

  //the compiler sign-extends A to 0xFFFFFFAA to keep the value negative
  b=(int)a; 

  b=b>>4; //right-shift maintains the sign-bit, so now you have 0xFFFFFFFA

【讨论】:

    【解决方案3】:

    标准允许charsignedunsigned,在您的情况下,它看起来像是signed。将0xAA 分配给signed charsigned overflow,因此是未定义的行为。因此,如果您将声明更改为:

    unsigned char a=0xAA;
    

    你应该得到你期望的结果。

    【讨论】:

      猜你喜欢
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      • 2022-12-20
      • 1970-01-01
      • 2015-09-12
      • 2018-08-16
      相关资源
      最近更新 更多