C中的十六进制

C中的十六进制,c,hex,C,Hex,我很困惑。为什么在这个程序中a给我0xffffa0而b给我0xA0?真奇怪 #include <stdio.h> int main() { char a = 0xA0; int b = 0xA0; printf("a = %x\n", a); printf("b = %x\n", b); } #包括 int main() { 字符a=0xA0; int b=0xA0; printf(“a=%x\n”,a); printf(“b=%x\n”,b);

我很困惑。为什么在这个程序中a给我0xffffa0b给我0xA0?真奇怪

#include <stdio.h>
int main()
{
    char a = 0xA0;
    int b = 0xA0;

    printf("a = %x\n", a);
    printf("b = %x\n", b);
}
#包括
int main()
{
字符a=0xA0;
int b=0xA0;
printf(“a=%x\n”,a);
printf(“b=%x\n”,b);
}

默认类型的
a
字符a=0xA0中的
签名
和在任何
有符号数据类型
中,无论其
字符是否为int
,都应注意
符号位
,如果
符号位
设置
则表示数字为负数,并以
两位互补
的方式存储

char a = 0xA0; /* only 1 byte for a but since sign bit is set, 
              it gets copied into remaining bytes also */

a  =>                                     1010 0000
                                          |
                                        this sign bit gets copied
        1111 1111  1111 1111  1111 1111   1010 0000
         f    f      f   f     f    f      A    0  

如果
int b=0xA0
符号位(第31位)
0
,因此将打印其中包含的内容,即
0xA0

让我们一步一步来


0xA0
在值为160的整数常量中,键入
int

在OP的例子中,
char
被编码为具有8位范围的
signed char
。160大于最大8位
char
,因此将超出范围的值分配给某个有符号整数类型是实现定义的行为。在OP的例子中,值“环绕”和
a
的值为160-256或-96

// Try
printf("a = %d\n", a);

使用
printf()
(a),
char a
将其传递到
部分,从而通过通常的整数升级到
int
,并保留相同的值

printf("a = %x\n", a);
// is just like
printf("a = %x\n", -96);

对于
printf()
%x“
期望值在非负范围内的
无符号
int
。对于
int
和-96,两者都不是,因此输出是未定义的行为

典型的未定义行为是将传递的位模式解释为无符号的。
int
-96的位模式作为32位
int
是0xFFFF0


故事的寓意:

  • 启用编译警告。一个好的编译器会对
    chara=0xA0
    printf(“a=%x\n”,a)

  • 不要依赖未定义的行为


  • 因为
    char
    signed
    ,所以
    0xA0
    是负数。没有混淆的理由。由于您没有指定,编译器正在对
    int
    char
    使用其默认签名。
    printf
    格式说明符
    %x
    不知道它被传递了
    int
    (第二种情况)或升级为
    int
    (第一种情况)的
    char
    ,它会处理它所提供的数据,在预期
    无符号int
    的上下文中,“默认情况下,
    a
    的类型是有符号的”-->不,它不是。它类似于OP的
    带符号字符,但这不是默认值。
    
    printf("a = %x\n", a);
    // is just like
    printf("a = %x\n", -96);
    
    printf("a = %x\n", a);