gpt4 book ai didi

c - 为什么整数提升的结果不同?

转载 作者:太空狗 更新时间:2023-10-29 16:33:53 25 4
gpt4 key购买 nike

请看我的测试代码:

#include <stdlib.h>
#include <stdio.h>


#define PRINT_COMPARE_RESULT(a, b) \
if (a > b) { \
printf( #a " > " #b "\n"); \
} \
else if (a < b) { \
printf( #a " < " #b "\n"); \
} \
else { \
printf( #a " = " #b "\n" ); \
}

int main()
{
signed int a = -1;
unsigned int b = 2;
signed short c = -1;
unsigned short d = 2;

PRINT_COMPARE_RESULT(a,b);
PRINT_COMPARE_RESULT(c,d);

return 0;
}

结果如下:

a > b
c < d

我的平台是Linux,我的gcc版本是4.4.2。我对第二行输出感到惊讶。第一行输出是由整数提升引起的。但是为什么第二行的结果不一样呢?

以下规则来自C99标准:

If both operands have the same type, then no further conversion is needed. 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.

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.

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.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

我觉得这两次比较应该属于同一种情况,整数提升的第二种情况。

最佳答案

当您使用算术运算符时,操作数会经过两次转换。

整数提升:如果int可以表示该类型的所有值,则操作数被提升为 int。这适用于 shortunsigned short在大多数平台上。在此阶段执行的转换是针对每个操作数单独完成的,而不考虑其他操作数。 (还有更多规则,但这是适用的规则。)

通常的算术转换:如果你比较 unsigned int针对 signed int ,因为两者都不包括另一个的整个范围,并且两者具有相同的排名,那么两者都被转换为 unsigned类型。此转换是在检查两个操作数的类型后完成的。

显然,如果没有两个操作数,“通常的算术转换”并不总是适用。这就是为什么有两套规则。例如,一个问题是移位运算符 <<>>不要做通常的算术转换,因为结果的类型应该只取决于左操作数(所以如果你看到有人输入 x << 5U ,那么 U 代表“不必要的”)。

分解:让我们假设一个典型的系统有 32 位 int 和 16 位 short。

int a = -1;         // "signed" is implied
unsigned b = 2; // "int" is implied
if (a < b)
puts("a < b"); // not printed
else
puts("a >= b"); // printed
  1. 首先提升两个操作数。因为两者都是 intunsigned int , 没有促销事件。
  2. 接下来,将两个操作数转换为相同的类型。自 int不能表示 unsigned 的所有可能值, 和 unsigned不能表示 int 的所有可能值,没有明显的选择。在这种情况下,两者都转换为 unsigned .
  3. 从有符号数转换为无符号数时,232 被重复添加到有符号数,直到它在无符号数的范围内。就处理器而言,这实际上是一个 noop。
  4. 所以比较变成if (4294967295u < 2u) , 这是错误的。

现在让我们用 short 试试看:

short c = -1;          // "signed" is implied
unsigned short d = 2;
if (c < d)
puts("c < d"); // printed
else
puts("c >= d"); // not printed
  1. 首先,提升两个操作数。因为两者都可以忠实地表示为 int , 两者都提升为 int .
  2. 接下来,将它们转换为相同的类型。但它们已经是同一类型,int , 所以什么也没做。
  3. 所以比较变成if (-1 < 2) , 这是真的。

编写好的代码:有一种简单的方法可以在您的代码中捕获这些“陷阱”。始终在打开警告的情况下进行编译,并修复警告。我倾向于这样写代码:

int x = ...;
unsigned y = ...;
if (x < 0 || (unsigned) x < y)
...;

您必须注意,您编写的任何代码都不会遇到其他有符​​号与无符号陷阱:有符号溢出。例如下面的代码:

int x = ..., y = ...;
if (x + 100 < y + 100)
...;
unsigned a = ..., b = ...;
if (a + 100 < b + 100)
...;

一些流行的编译器会优化(x + 100 < y + 100)(x < y) ,但这是另一天的故事。只是不要溢出您的签名号码。

Footnote: Note that while signed is implied for int, short, long, and long long, it is NOT implied for char. Instead, it depends on the platform.

关于c - 为什么整数提升的结果不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7711124/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com