gsa*_*ras 175 c expression operators compiler-warnings comma-operator
在阅读有关未定义行为和序列点的答案后,我写了一个小程序:
#include <stdio.h>
int main(void) {
int i = 5;
i = (i, ++i, 1) + 1;
printf("%d\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是2.天啊,我没有看到减量来了!这里发生了什么?
另外,在编译上面的代码时,我收到一条警告:
px.c:5:8:警告:逗号表达式的左侧操作数无效
Run Code Online (Sandbox Code Playgroud)[-Wunused-value] i = (i, ++i, 1) + 1; ^
为什么?但可能会通过我的第一个问题的答案自动回答.
hac*_*cks 257
在表达式中(i, ++i, 1),使用的逗号是逗号运算符
逗号运算符(由标记表示
,)是一个二元运算符,它计算其第一个操作数并丢弃结果,然后计算第二个操作数并返回该值(和类型).
因为它丢弃了它的第一个操作数,所以它通常仅在第一个操作数具有所需副作用的情况下才有用.如果没有发生对第一个操作数的副作用,则编译器可能会生成有关表达式的警告而不起作用.
因此,在上面的表达式中,i将评估最左边的值,并且将丢弃其值.然后++i将被评估并将增加i1并且表达式的值++i将被丢弃,但副作用i是永久的.然后1将进行评估,表达式的值将是1.
它相当于
i; // Evaluate i and discard its value. This has no effect.
++i; // Evaluate i and increment it by 1 and discard the value of expression ++i
i = 1 + 1;
Run Code Online (Sandbox Code Playgroud)
请注意,上面的表达式是完全有效的,并且不会调用未定义的行为,因为在对逗号运算符的左右操作数的求值之间存在一个序列点.
Sou*_*osh 62
引用C11,章节6.5.17,逗号运算符
逗号运算符的左操作数被计算为void表达式; 它的评估与右操作数之间存在一个序列点.然后评估右操作数; 结果有它的类型和价值.
所以,在你的情况下,
(i, ++i, 1)
Run Code Online (Sandbox Code Playgroud)
被评估为
i,被评估为void表达式,值被丢弃++i,被评估为void表达式,值被丢弃1返回值.所以,最后的陈述看起来像
i = 1 + 1;
Run Code Online (Sandbox Code Playgroud)
并i得到2.我想这可以解答你的两个问题,
i获得价值2?注意:FWIW,因为有一个顺序点的左手操作数的评价之后存在,就像表达式(i, ++i, 1)将不会调用UB,作为一个可能通常误认为.
dla*_*ask 30
i = (i, ++i, 1) + 1;
Run Code Online (Sandbox Code Playgroud)
让我们一步一步地分析它.
(i, // is evaluated but ignored, there are other expressions after comma
++i, // i is updated but the resulting value is ignored too
1) // this value is finally used
+ 1 // 1 is added to the previous value 1
Run Code Online (Sandbox Code Playgroud)
所以我们得到2.最后的任务现在:
i = 2;
Run Code Online (Sandbox Code Playgroud)
无论我现在被覆盖之前是什么.
Gop*_*opi 19
结果
(i, ++i, 1)
Run Code Online (Sandbox Code Playgroud)
是
1
Run Code Online (Sandbox Code Playgroud)
对于
(i,++i,1)
Run Code Online (Sandbox Code Playgroud)
评估发生时,,操作员丢弃评估值并保留最正确的值1
所以
i = 1 + 1 = 2
Run Code Online (Sandbox Code Playgroud)
Tom*_*han 14
你会在Comma运营商的维基页面上找到一些好的阅读材料.
基本上,它
...计算其第一个操作数并丢弃结果,然后计算第二个操作数并返回该值(和类型).
这意味着
(i, i++, 1)
Run Code Online (Sandbox Code Playgroud)
反过来,将评估i,丢弃结果,评估i++,丢弃结果,然后评估并返回1.
son*_*yao 13
你需要知道逗号运算符在这里做了什么:
你的表达:
(i, ++i, 1)
Run Code Online (Sandbox Code Playgroud)
计算第一个表达式,i计算第二个表达式++i,并1为整个表达式返回第三个表达式.
结果是:i = 1 + 1.
对于你的奖金问题,如你所见,第一个表达式i根本没有效果,所以编译器会抱怨.
逗号具有"反向"优先权.这是您从IBM(70年代/ 80年代)的旧书和C手册中获得的内容.所以最后一个'命令'是父表达式中使用的.
在现代C中,它的使用很奇怪但在旧C(ANSI)中非常有趣:
do {
/* bla bla bla, consider conditional flow with several continue's */
} while ( prepAnything(), doSomethingElse(), logic_operation);
Run Code Online (Sandbox Code Playgroud)
虽然从左到右调用所有操作(函数),但只有最后一个表达式将用作条件'while'的结果.这样可以防止处理'goto'以在条件检查之前保持一个唯一的命令块.
编辑:这也避免了对处理函数的调用,该处理函数可以处理左操作数的所有逻辑,因此返回逻辑结果.请记住,我们在C的过去没有内联函数.因此,这可以避免调用开销.
| 归档时间: |
|
| 查看次数: |
17170 次 |
| 最近记录: |