【问题标题】:Why is a number sign-extended when it is cast to an unsigned type?为什么将数字符号转换为无符号类型时会对其进行扩展?
【发布时间】:2019-10-22 11:25:13
【问题描述】:

我正在研究 C 如何按位模式将数据存储在内存中。
但是,在printf 格式方面,我遇到了一些问题。

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

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

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

printf("a : %x , b : %x\n" , (unsigned int) a, (unsigned int) b);
//a : fffffff6 , b : f6

两个整数具有相同的位模式0xF6。但是,如果我确实将类型转换为unsigned int,结果会有所不同。结果是0xFFFFFFF6 对应a,而b 保持不变。

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

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

【问题讨论】:

  • 是的。当提升为更大的有符号整数类型时,符号位向左扩展。因此所有 1 位。无符号整数类型没有符号位,因此全为零。
  • @PaulOgilvie 符号位是否在强制转换为更大的无符号类型时扩展?
  • @JL2210 抱歉在我的问题中犯了太多错误。我对这个论坛很陌生,英语不是我的母语...非常感谢您将我的帖子编辑成更易读的形式!
  • 您看到的行为是正确的,而您的期望是错误的。 (unsigned)(-10) == UINT_MAX - 9。您期望的结果(错误地)假定(unsigned)(-10) == UCHAR_MAX - 9

标签: c printf


【解决方案1】:

在这个表达式中

(unsigned int) a

整数提升应用于对象a

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

2 以下可以在表达式中使用 int 或 可以使用无符号整数:

- 具有整数类型的对象或表达式(除了 int 或 unsigned int) 其整数转换等级小于或等于 int 和 unsigned int 的等级。

— _Bool、int、signed int 或 unsigned int 类型的位域。

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

3 整数促销保留价值,包括符号。正如所讨论的 早些时候,“普通”字符是否被视为已签名是 实现定义。

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

(unsigned char) a

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

printf("a : %x , b : %x\n" , (unsigned char) a, (unsigned int) b);

【讨论】:

  • 这是否意味着由于原始对象具有符号位,通过从有符号字符到有符号整数的类型转换,由于保留了包括符号在内的值,所以空位变为填充 1?
  • @Gooday2die 是的,将有符号整数对象转换为具有更大大小的无符号整数对象会传播符号位。
  • @Gooday2die:不。C 标准通过对象表示的定义这些转换,而不是通过它们的位模式。几乎所有现代 C 实现都使用二进制补码,其中将有符号类型转换为无符号类型产生的位与传播符号位产生的位相同。但是,C 标准也允许补码、符号和量值。使用这些时,转换遵循值的规则,而不是传播位的任何规则。
  • 弗拉德,我现在明白了吗,在签名的char a(unsigned int) a 中,first a 被提升为更大的整数类型作为参数函数调用,并且 then 被解释为余数为unsigned int(因为没有剩余的表达式,所以不需要)?
  • @PaulOgilvie a 被转换为 unsigned int 类型,以 2 的补码表示形式传播符号位。使用 ( unsigned char )a a 现在被解释为 unsigned char 并且由于转换,符号位没有被传播,因为现在 a 没有符号位。这是一个价值位..
猜你喜欢
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2019-11-08
  • 2018-04-06
  • 2016-02-17
相关资源
最近更新 更多