“?:”中发生了什么?我不知道 return 类型

What is happening in "? :"? I have no idea about the return type

我认为 ((1 ? (int)1 : (unsigned int)2) > -1) 的结果是 1(正确),但实际上在 Visual Studio 2017 中是 0(错误)。

我认为(1 ? (int)1 : (unsigned int)2)的值应该是(int)1,因为1 ?是真的,1 > -1也是真的。

不知道为什么这个表达式最后的结果是假的

当我尝试像 ((int)(1 ? (int)1 : (unsigned int)2) > -1) 那样进行转换时,它 returns 1 (true)。

signed int test = -1;
signed int si = 1;
unsigned int ui = 2;

printf("%d\n", ((1 ? si : ui) > test));
return 0;

我希望输出为 1,但实际输出为 0

a ? b : c 的类型不依赖于 a。由bc的类型无条件决定。完整的规则很复杂,但是对于算术操作数,类型由通常的算术转换决定。实际上,这两个操作数被转换为通用类型。对于 intunsigned int,结果类型是 unsigned int.

条件运算符 ? : 在 C 2018 标准的第 6.5.15 条中进行了描述。第 4 段说结果“转换为下面描述的类型”。

第 5 段描述了算术类型、结构和联合的结果:

If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.

算术类型是整数和浮点类型,根据 6.2.5 18。(这些包括实数和复数类型。)通常的算术转换在 6.3.1.8 1 中描述,它们是(在我的总结中,未引用):

  • 如果其中一个是复数类型,则结果为复数,其余规则描述实部和虚部的类型。否则,结果为真实,其余规则描述其类型。
  • 如果其中一个是long double,结果是long double
  • 否则,如果任一个为double,则结果为double
  • 否则,如果任一个为float,则结果为float
  • 否则,整数提升应用于每个操作数(这些在 6.3.1.1 2 中指定),然后将两种类型转换为通用整数类型。完整的规则有点复杂,使用需要一些解释的等级概念,并涵盖一些深奥的情况,所以我只针对正常情况总结它们:如果两种类型都是 int 或更窄(意味着更少的位或相同的位数但有符号而不是无符号),结果是 int。否则,如果两者都为 unsigned int 或更窄,则结果为 unsigned int。否则,结果是更宽的类型。

structure、union、void规则很明确:两个操作数的类型必须相同,就是结果。

第 6 段描述了指针的结果:

If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the result type is a pointer to an appropriately qualified version of void.

总而言之,就是:

  • 如果任一操作数具有限定符(constvolatilerestrict_Atomic),则将其包含在结果类型中。
  • 如果这两种类型不同但兼容(例如未知大小的数组和已知大小的数组,两者具有相同类型的元素),则将这两种类型结合起来。 (除了数组大小之外,其他组合的可能性包括数组的元素是不同但兼容的类型,一个有和没有参数列表的函数,以及函数的参数是不同但兼容的类型。)

你不应该混合有符号和无符号的值,除非你完全知道正在展开的是什么(并且你想要这种行为)[checkout here why]。在幕后,因为你的表达式中有一个 unsigned 数字,C 被评估为你的大于运算符 unsigned integer >。因此,您的比较不会评估 true,因为“unsigned -1”大于您的 unsigned 1

只是为了给它加上一个数字,如果我放弃这个代码:

unsigned x = (unsigned)-1;

进入我正在调试的程序,X 的值为 4294967295 (UINT_MAX),即您的程序 "sees" 比较如下:

((1 ? (int)1 : (unsigned int)2) > 4294967296)

(本来可以作为评论输入的,但我没有名气。)

?: 运算符的结果是无符号类型,因为它是 intunsignedcommon 类型(您的第二个和第三个操作数)。结果的 "expected" 值为 1,但其类型为 unsigned.

其余的与?:完全无关。在这个常见问题的许多答案中都有很好的描述:Comparison operation on unsigned and signed integers