假设我有以下C代码.

unsigned int u = 1234;
int i = -5678;

unsigned int result = u + i;

这里正在进行什么隐式转换,这段代码对所有值ui都安全吗?(安全,从这个意义上说,即使本例中的result将溢出到某个巨大的正数,我也可以将其转换回int并获得真正的结果.)

推荐答案

Short Answer

通过加UINT_MAX + 1,你的i将是converted到一个无符号整数,然后用无符号值进行加法,得到一个大的result(取决于ui的值).

Long Answer

根据C99标准:

6.3.1.8常用算术转换

  1. 如果两个操作数的类型相同,则无需进一步转换.
  2. 否则,如果两个操作数都具有带符号整数类型或都具有无符号整数类型,则将具有较小整数转换秩的类型的操作数转换为具有较大秩的操作数的类型.
  3. 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则具有有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型.
  4. 否则,如果有符号整数类型的操作数的类型可以表示无符号整数类型的操作数类型的所有值,则无符号整数类型的操作数将转换为有符号整数类型的操作数的类型.
  5. 否则,两个操作数都将转换为与带符号整数类型的操作数类型对应的无符号整数类型.

在你的例子中,我们有一个无符号整数(u)和有符号整数(i).参考上面的(3),由于两个操作数的秩相同,i必须是converted到无符号整数.

6.3.1.3有符号和无符号整数

  1. 当整数类型的值转换为除_Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变.
  2. 否则,如果新类型是无符号的,则会通过反复将新类型中可以表示的最大值加上或减go 一个来转换该值,直到该值在新类型的范围内.
  3. 否则,新类型将被签名,并且无法在其中表示值;要么结果是实现定义的,要么发出实现定义的信号.

现在我们需要参考上面的(2).您的i将通过添加UINT_MAX + 1转换为无符号值.因此,结果将取决于如何在实现中定义UINT_MAX.它会很大,但不会溢出,因为:

6.2.5 (9)

涉及无符号操作数的计算永远不会溢出,因为不能由结果无符号整数类型表示的结果将被减少为比结果类型可以表示的最大值大一的数的模.

Bonus: Arithmetic Conversion Semi-WTF

#include <stdio.h>

int main(void)
{
  unsigned int plus_one = 1;
  int minus_one = -1;

  if(plus_one < minus_one)
    printf("1 < -1");
  else
    printf("boring");

  return 0;
}

你可以使用此链接在线try :https://repl.it/repls/QuickWhimsicalBytes

Bonus: Arithmetic Conversion Side Effect

算术转换规则可用于通过将无符号值初始化为-1来获得UINT_MAX的值,即:

unsigned int umax = -1; // umax set to UINT_MAX

由于上面描述的转换规则,无论系统的符号数字表示形式如何,这都保证是可移植的.更多信息请参见此问题:Is it safe to use -1 to set all bits to true?

C++相关问答推荐

Linux/C:复制修剪了最后一个填零孔的文件

漏洞仅出现在FreeBSD上,但在Windows、Linux和MacOS上运行得非常好

在Windows上构建无聊的SSL x64

C语言中字符数组声明中的标准

Linux不想运行编译后的文件

在C语言中,是否可以使枚举数向后计数?

如何使用C++在控制台中以彩色打印被阻止的客户端

C:在编译时构建和使用字符串文字的预处理器宏?

在函数外部使用内联ASM时无法指定操作数

为四维数组中的Dim-1和Dim-3重新分配空间

在C程序中使用Beaglebone Black UART的问题

`预期说明符-限定符-列表在‘(三元运算符中的’token`‘之前

将非连续物理内存映射到用户空间

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

GETS()在C++中重复它前面的行

";错误:寄存器的使用无效;当使用-masm=intel;在gcc中,但在AT&;T模式

C循环条件内的函数

从管道读取数据时丢失

C 中从 Unix 纪元时间转换的损坏

如何在 C 中的 Postgres 函数的表中 for 循环