?: 运算符在 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 中究竟是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章
程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?
程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?