【问题标题】:bitwise shift promotes unsigned char to int按位移位将 unsigned char 提升为 int
【发布时间】:2013-07-05 13:08:53
【问题描述】:

以下代码:

unsigned char result;
result = (result << 4 );

使用 gcc 版本 4.6.4 (Debian 4.6.4-2) 编译,带有 -Wconversion 标志会导致警告

警告:从“int”转换为“unsigned char”可能会改变其值 [-Wconversion]

为什么会这样?

【问题讨论】:

标签: c++ linux gcc


【解决方案1】:

因为标准是这样说的。二元运算符的操作数 进行整体晋升,其中任何小于 int 提升为int;手术结果有 也输入int。如果原始值是,比如说, 0x12,结果将是 0x120,并将其分配给 unsigned char 将导致值发生变化。 (指定的 值将是0x20。)警告从何而来。

编辑:

从标准(§5.8 移位运算符):“操作数应 是整数或非范围枚举类型和整数 进行促销。结果的类型是 提升左操作数。”与其他二元运算符不同,有 没有努力从两个运算符中找到一个共同的类型: 结果类型是左操作数的类型,句点。但积分 促销确实仍然发生:unsigned char 将是 提升为int(或unsigned int,如果int的大小为 1).

【讨论】:

  • 我是唯一一个对警告状态“从 int 到 unsigned char”感到困扰的人吗?听起来不像整数提升,而是将数字文字 int 减少为无符号字符。 GCC 8.3.0 甚至用^ 标记而不是result 变量来指定数字文字。
  • 我现在已经多次在这个该死的“常规算术转换”中“摔断了腿”。调试我的代码几天和几个小时,最终一遍又一遍地揭示这个标准....
  • 我知道这是为了优化(ints 操作比 char/short 操作运行得更快),但这会导致很多不便和模棱两可,我不确定为什么标准没有承认这一点。
【解决方案2】:

因为int 的值可能大于unsigned char 的值。

想想当result255(即0xff)会发生什么。将其向左移动四位将使其成为4080(或0xff0)。编译器如何能够将该值压缩回result?它不能,所以它只是将其截断为240 (0xf0)。换句话说,integer操作result &lt;&lt; 4的值可能会被改变。

【讨论】:

  • 这句话虽然是对的,但非常模糊。
  • @HunterMcMillen 我同意。我认为原始问题的要点是int 的来源。
【解决方案3】:

所有算术和逻辑运算符都对其参数执行“整数提升”。积分提升将小于int(如unsigned char)的类型转换为intunsigned int。如果将 &lt;&lt; 替换为 +,您会看到同样的结果。

哦,不需要括号。

【讨论】:

  • 是否消除警告取决于编译器。甚至result &lt;&lt;= 4 也涉及缩小转换(当然,编译器可以随意警告它想要的任何东西)。
  • @JamesKanze - 是的。已删除。
猜你喜欢
  • 1970-01-01
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多