当将十六进制值“0x000000a1”分配给(有符号)char 时,char 等于“0xffffffa1”。 谁能解释一下这种奇怪的行为吗?
void main(){
char testVar = 0x000000a1;
printf("%x \n",testVar); //prints ffffffa1
printf("%d \n",testVar); //prints -95
}
当您初始化无符号字符时,它会按预期工作
void main(){
unsigned char testVar = 0x000000a1;
printf("%x \n",testVar); //prints a1
printf("%d \n",testVar); //prints 161
}
当您分配 ASCII 限制 127(或 0x7f)内的值时,也可以按预期工作
void main(){
unsigned char testVar = 0x7f;
printf("%x \n",testVar); //prints 7f
printf("%d \n",testVar); //prints 127
}
问完问题后我现在明白了:
不能将 0x000000a1 分配给字符,因为字符只有 2 个字节长。您只分配 a1 部分。
A
char
根据定义always 1 字节大。 (不过,在外来系统上它可能有超过 8 位。)这里的关键不是 char
具有实现定义的签名:它可以是有符号的或无符号的,具体取决于编译器。 char 默认情况下是签名还是未签名? 显然在你的情况下它是签名的。
值前面的零数量没有丝毫影响,也不影响类型。他们所做的只是愚弄程序员,认为他们有一定的意义。
有符号值的第一位表示是否为负数(1000 0000 为负数,等于 -128。0111111 不是负数,等于 127)
是的,如果是 MSB。
将
0xa1
赋值给 signed char
时会发生什么也是特定于编译器的。在主流系统上,这将导致负的二进制补码值-95
十进制。
或者某些原因 printf 需要将 char 变量扩展为 int 才能输出值。
printf
是一个可变参数函数(可变数量的参数),对于这些函数,有一个特殊的隐式类型提升规则,称为“默认参数提升”。当将小整数类型(例如 char
或 short
)传递给可变参数函数时,它总是会隐式提升为 int
。 (当通过float
时,它将晋升为double
。)
当 printf 将有符号 char 转换为 int 时,它会识别 char 何时为负数,因此通过用 1 而不是 0 扩展来保留负值
正确。在此促销期间,如果您的原始类型已签名且具有负值,则会尊重这一点并保留符号,即所谓的“符号扩展”。因此,在事物的二进制表示中,您得到的是
char
0xffffffa1 = 仍然 -95,而不是(有符号)int
0xa1 = -95。
然后你用
%x
对 printf 撒谎,告诉它需要一个 unsigned int
参数。严格来说,这是未定义的行为,但任何明智的编译器都会将 int
转换为 unsigned int
,这是一个明确定义的转换,留下 0xffffffa1 但现在它是无符号表示,因此它等于十进制值 4294967201。