?: 运算符在 C 中究竟是如何工作的?

Posted

技术标签:

【中文标题】?: 运算符在 C 中究竟是如何工作的?【英文标题】:How exactly does the ?: operator work in C? 【发布时间】:2020-05-26 20:51:38 【问题描述】:

我有一个问题,编译器如何对以下代码进行操作:

#include<stdio.h>

int main(void)

  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);

我不确定为什么结果是 ‍‍‍d = 11

【问题讨论】:

你为什么不确定?您还期望什么?为什么? 我不记得所涉及的确切语义,但您可能正在观察未定义的行为。 不,@chepner,在评估三元的条件之后,在评估选定的替代方案之前,有一个序列点。这避免了我想你正在考虑的 UB 向量。 是的,我不确定我认为编译器会在哪里选择。 【参考方案1】:

int d = (b == c++) ? (c+1) : (c-1);:

c++ 的值是c 的当前值,11。另外,c 递增到 12。 b == 11 是假的,因为 b 是 12。 由于(b == c++) 为假,因此使用(c-1)。此外,c 到 12 的增量必须在此时完成。 因为c 是12,所以c-1 是11。 d 被初始化为那个值,11。

【讨论】:

【参考方案2】:

根据 C 标准(6.5.15 条件运算符)

4 计算第一个操作数;之间有一个序列点 它的评估和第二个或第三个操作数的评估 (以评估为准)。只有当 首先比较不等于0;仅在以下情况下评估第三个操作数 第一个比较等于 0;结果是第二个的值 或第三个操作数(以被评估者为准),转换为类型 如下所述。110)

所以在这个声明的初始化表达式中

int d = (b == c++) ? (c+1) : (c-1);

变量b 与变量c 的值进行比较,因为后自增运算符在自增之前返回其操作数的值。

由于值不相等(b 设置为 12,而 c 设置为 11),因此计算子表达式 (c-1)

根据引用,在评估运算符的条件之后有一个序列点。这意味着在对变量 c 应用后增量运算符后,评估条件 c 具有值 12。结果,变量 d 由值 1 (12 - 1) 初始化。

【讨论】:

唯一正确的答案——这个具体案例必须通过提及?:中的序列点来回答。因为通常在 C 中,将 ++ 与同一操作数上的其他操作组合是未定义的行为。这段代码只能按预期工作,因为?: 有各种特殊的雪花规则。【参考方案3】:

因为条件为假,因此false 的情况将发生:c-1,但由于您在条件中将c 增加了c++,因此c 现在是12。因此结果为 12 - 1,即 11。

编辑: OP 误解的是帖子增量。

所以实际发生的事情是这样的:

#include<stdio.h>
int main(void)

  int b=12, c=11;
  int d;

  if (b == c)  // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
   else  // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  
  printf("d = %i\n", d);

【讨论】:

鉴于条件中的c++,我认为OP指的是操作顺序。条件为假,但随后c原始 值用于计算c - 1,而不是增量版本。 但这不是真的,因为使用了新的 c 值还是我错过了你的观点? 我认为c++++c之间可能存在误解 @N00b c++post 增量运算符。 c++ 的值为 11,产生了c == 12 的副作用。 ++c 的值为 12。 实际上会发生12 == 11条件检查,然后c递增。【参考方案4】:

转换为常规 if 语句,您的代码将如下所示:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

这里的线索是 c 在检查条件之后 递增。所以你进入了else 状态,但是 c 已经有值 12 了。

【讨论】:

【参考方案5】:

参考Ternary Operator.

语法

条件? value_if_true : value_if_false

所以,你写了

int d = (b == c++) ? (c+1) : (c-1);

在这种情况下,结果将是 11,因为在 if 检查之后,'c' 值增加了(c+1=12),并且只有在那之后它才将 'd' 值设置为 c(12)-1,即11.

如果你使用过,例如:

int d = (b == ++c) ? (c+1) : (c-1);

“c”值会在检查语句之前增加,所以它是真的,“d”值将是 c(12)+1,即 13。

【讨论】:

以上是关于?: 运算符在 C 中究竟是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

炮兵:ramto 在炮兵中究竟是如何工作的?

会话劫持在 PHP 中究竟是如何工作的?

程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?

程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?

技能意志矩阵-skill will matrix工作中究竟是个人能力更重要,还是我们的积极性更能提高我们的业绩?

帧缓冲区在 Vulkan 中究竟是啥意思