为什么数字在转换为无符号类型时会进行符号扩展?

Goo*_*die 4 c printf

我正在研究C如何通过位模式在内存中存储数据。
然而,在格式化方面我遇到了一些问题printf

我已将一个变量保存为-10(我确实理解二进制补码),将另一个变量保存为246. 这两个变量的位模式为11110110(即0xF6)。

我试图使用unsigned int十六进制格式打印出一个值printf

char a = -10; 
unsigned char b = 246;

printf("a : %x , b : %x\n" , (unsigned int) a, (unsigned int) b);
//a : fffffff6 , b : f6
Run Code Online (Sandbox Code Playgroud)

两个整数具有相同的位模式0xF6。但是,如果我执行类型转换到unsigned int,结果会有所不同。结果0xFFFFFFF6a,而b保持不变。

对于有符号字符,在我看来,类型转换过程将 变为unsigned char整数,并用 1 填充所有空位。

这是因为他们的签名吗?或者这只是未定义的行为?

Vla*_*cow 5

在这个表达式中

\n
(unsigned int) a\n
Run Code Online (Sandbox Code Playgroud)\n

整数提升应用于对象a

\n

来自 C 标准(6.3.1.1 布尔值、字符和整数)

\n
\n

2 只要可以使用 int 或unsigned int,就可以在表达式中使用以下内容:

\n

\xe2\x80\x94 具有整数类型(除 int 或\nunsigned int 之外)的对象或表达式,其整数转换等级小于或等于\nint 和 unsigned int 的等级。

\n

\xe2\x80\x94 _Bool、int、signed int 或 unsigned int 类型的位字段。

\n

如果 int 可以表示原始类型的所有值(对于位域,受宽度限制),则该值将转换为 int;否则,它将转换为无符号 int。这些称为\n整数促销。58) 所有其他类型都不会因整数促销而改变。

\n
\n

\n
\n

3整数提升保留包括符号在内的值。如前所述, \xe2\x80\x98\xe2\x80\x98plain\xe2\x80\x99\xe2\x80\x99 字符是否被视为有符号是由实现定义的。

\n
\n

如果您希望在转换后的结果对象中将字符对象表示为具有该类型,unsigned char那么您必须编写

\n
(unsigned char) a\n
Run Code Online (Sandbox Code Playgroud)\n

由于提升表达式的值(unsigned char) a可以用类型表示,因此不需要unsigned int第二次强制转换 (to )。如果值以两种类型表示,则unsigned intC 标准允许使用类型参数int而不是类型。unsigned int你可以只写

\n
printf("a : %x , b : %x\\n" , (unsigned char) a, (unsigned int) b);\n
Run Code Online (Sandbox Code Playgroud)\n

  • @Gooday2die:不。C 标准通过对象表示的 **值** 定义这些转换,而不是通过其位的模式。几乎所有现代 C 实现都使用二进制补码,其中将有符号类型转换为无符号类型所产生的位与传播符号位所产生的位相同。然而,C 标准也允许补码、符号和大小。当使用这些时,转换遵循值的规则,而不是传播位的任何规则。 (2认同)