三元运算符逻辑

Ternary operator logic

我需要根据条件将双精度数转换为整数,但是当我使用三元运算符时,我得到了一些奇怪的结果。我写了这个简单的程序来测试我的逻辑,但我不明白发生了什么。

#include <stdio.h>

int main()
{
  double n = 50.0;

  printf("%i\n", (int)n);

  printf("%i\n", ((1) ? (int)n : n));

  printf("%i\n", ((1) ? n : (int)n));

  printf("%i\n", ((0) ? (int)n : n));

  printf("%i\n", ((0) ? n : (int)n));

  return 0;
}

我希望得到以下输出:

50
50
0
0
50

但我得到的输出是:

50
0
0
0
0

你一下子被C语言的两个阴暗角落绊倒了。

  1. 给定 double n,“usual arithmetic conversions”导致 (ANYTHING ? (int)n : n)(ANYTHING ? n : (int)n) 都具有类型 double。也就是说,如果采用 (int)n 分支,值 n 将转换为 int ,然后返回 double

  2. printf("%i\n", (double)whatever) 引发未定义的行为。这是因为 printf 依赖其格式字符串来了解其可变参数的类型。如果你告诉它打印一个 int 但你传递了一个 double 它会在错误的地方查找要打印的值。

由于 (1),(2) 影响所有四个包含三元表达式的 printf 语句,而不仅仅是那些未采用 cast-to-int 分支的语句。

我不明白你想用 (condition ? (int)n : n) 完成什么,所以我不能告诉你你应该怎么做。

当三目运算符的第二个和第三个操作数类型不同时,使用usual arithmetic conversions将它们自动转换为相同类型。因此,仅对其中一个操作数进行强制转换不会产生您预期的效果——(int) n 将被强制转换回 double,这将是三元表达式的类型。

这将被传递给 printf,并且您将得到未定义的行为,因为您正在尝试使用 %i 格式打印 double,该格式需要 int.

如果你想让参数的类型依赖于条件,你需要使用普通的if。例如,这显然是您在第一个三元示例中试图完成的:

if (1) {
    printf("%i\n", (int) n); // valid
} else {
    printf("%i\n", n); // invalid
}

在 'conditional operator' 的标准中说:

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.

因为你有 intdouble 作为类型,条件的结果总是 double,所以当你用错误的方式打印它时,你会得到任何垃圾format — 这是调用未定义的行为和一个坏主意