c - 在 C 中签名到无符号的转换 - 它总是安全的吗?

标签 c type-conversion

假设我有以下 C 代码。

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

unsigned int result = u + i;

此处进行了哪些隐式转换,此代码对于 ui 的所有值是否安全? (安全的是,即使此示例中的 result 会溢出到某个巨大的正数,我也可以将其转换回 int 并获得真正的结果。)

最佳答案

简答题

您的 i 将通过添加 UINT_MAX + 1转换为无符号整数,然后将使用无符号值执行加法,导致较大的结果(取决于ui 的值)。

长答案

根据 C99 标准:

6.3.1.8 Usual arithmetic conversions

  1. If both operands have the same type, then no further conversion is needed.
  2. Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
  3. Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
  4. Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
  5. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

在您的例子中,我们有一个无符号整数 (u) 和一个有符号整数 (i)。引用上面的 (3),由于两个操作数具有相同的秩,因此您的 i 需要转换为无符号整数。

6.3.1.3 Signed and unsigned integers

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

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

6.2.5 (9)

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

奖励:算术转换半 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;
}

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

奖励:算术转换副作用

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

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

由于上述转换规则,无论系统的带符号数字表示如何,这都保证是可移植的。有关详细信息,请参阅此 SO 问题:Is it safe to use -1 to set all bits to true?

关于c - 在 C 中签名到无符号的转换 - 它总是安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19237295/

相关文章:

c++ - 如何在不丢失顺序的情况下将 std::vector 转换为 std::set

r - 将 POSIXct 向量转换为日期格式会在 R 中添加一天(9/30 变为 10/1)

string - 如何将GCI DirectoryName转换为.Substring()的字符串

c - 洪水填充算法

c - 使用 shm_open 在 C 结构中共享 char 指针

c - 如何用 C 语言实现这种外部合并排序算法?

json - Golang 中的类型转换

ios - NSString 的值是 iOS 中的 NSInteger 值吗

c - 从 C 中的字符串中去除数字

c - 为什么errno的值打印不出来?