C语言中的有符号到无符号的转换-总是安全的吗?
假设我有下面的C代码C语言中的有符号到无符号的转换-总是安全的吗?,c,type-conversion,C,Type Conversion,假设我有下面的C代码 unsigned int u = 1234; int i = -5678; unsigned int result = u + i; 这里正在进行什么隐式转换,对于u和i的所有值,该代码是否安全?(安全的,在这个意义上,即使本例中的结果将溢出到某个巨大的正数,我也可以将其转换回int并获得真实结果。)简短回答 您的i将通过添加UINT_MAX+1转换为无符号整数,然后使用无符号值进行加法,从而产生较大的结果(取决于u和i的值) 长答案 根据C99标准: 6.3.1.8常
unsigned int u = 1234;
int i = -5678;
unsigned int result = u + i;
这里正在进行什么隐式转换,对于
u
和i
的所有值,该代码是否安全?(安全的,在这个意义上,即使本例中的结果将溢出到某个巨大的正数,我也可以将其转换回int并获得真实结果。)简短回答
您的i
将通过添加UINT_MAX+1
转换为无符号整数,然后使用无符号值进行加法,从而产生较大的结果
(取决于u
和i
的值)
长答案
根据C99标准:
6.3.1.8常用算术转换
u
)和一个有符号int(i
)。参考上面的(3),由于两个操作数具有相同的秩,因此需要将i
转换为无符号整数
6.3.1.3有符号和无符号整数
i
将通过添加UINT\u MAX+1
转换为无符号值。因此,结果将取决于实现中如何定义UINT\u MAX
。它会很大,但不会溢出,因为:
6.2.5(9)
涉及无符号操作数的计算永远不会溢出,因为不能由结果无符号整数类型表示的结果将被减少为比结果类型可以表示的最大值大一的数的模
奖金:算术转换半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;
}
由于上面描述的转换规则,无论系统的符号数字表示形式如何,这都保证是可移植的。有关更多信息,请参阅此SO问题:当添加一个无符号变量和一个有符号变量(或任何二进制操作)时,这两个变量都会隐式转换为无符号变量,在本例中,这将导致巨大的结果
因此,从某种意义上讲,结果可能是巨大的、错误的,但它永远不会崩溃。当从有符号转换为无符号时,有两种可能性。最初为正的数字保留(或解释为)相同的值。原来为负数的数字现在将被解释为更大的正数。正如前面回答的,您可以在有符号和无符号之间来回转换,而不会出现问题。有符号整数的边界大小写为-1(0xFFFFFFFF)。尝试从中加减,你会发现你可以回溯,让它是正确的 但是,如果您要来回转换,我强烈建议您命名变量,以便清楚它们是什么类型,例如:
int iValue, iResult;
unsigned int uValue, uResult;
如果在没有提示的情况下命名变量,很容易被更重要的问题分散注意力,忘记哪个变量是什么类型。您不希望强制转换为无符号,然后将其用作数组索引。指:
- 加法操作将导致int转换为无符号int
- 假设二者的补码表示和大小相同的类型,位模式不会改变
- 从无符号整数到有符号整数的转换取决于实现。(但它的工作方式可能与目前大多数平台上的预期相同。)
- 在组合大小不同的有符号和无符号时,规则稍微复杂一些
int iValue, iResult;
unsigned int uValue, uResult;
unsigned int u = 1234;
int i = -5678;
unsigned int result = u + i;