什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
我找到了很多有关静态的文章(MSDN,MSDN 2,Stack Overflow等等),但是我仍然不明白为什么此代码返回-1:
class Program
{
static int value = 0;
static int foo()
{
value = value - 7;
return 1;
}
static void Main(string[] args)
{
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
这是调试器在foo()运行后但从中减去结果之前显示的内容value:
但是,下一步value是-1:
我希望-8因为静态字段存储在内存中一次。
当我将其更改为
var x = foo();
value -= x;
Run Code Online (Sandbox Code Playgroud)
表明 -8
究竟如何运作?
术语"运算符优先级"和"评估顺序"是编程中非常常用的术语,对于程序员来说非常重要.而且,据我所知,这两个概念紧密相连; 在谈论表达时,一个人离不开另一个人.
我们举一个简单的例子:
int a=1; // Line 1
a = a++ + ++a; // Line 2
printf("%d",a); // Line 3
Run Code Online (Sandbox Code Playgroud)
现在,很明显会Line 2导致未定义的行为,因为C和C++中的序列点包括:
在评估&&(逻辑AND)的左右操作数之间,|| (逻辑OR)和逗号运算符.例如,在表达式中
*p++ != 0 && *q++ != 0,子表达式的所有副作用*p++ != 0都在任何访问尝试之前完成q.在评估三元"问号"运算符的第一个操作数和第二个或第三个操作数之间.例如,在表达式中,在第
a = (*p++) ? (*p++) : 0一个之后存在一个序列点*p++,这意味着它已经在第二个实例执行时增加了.在完整表达结束时.此类别包括表达式语句(例如赋值
a=b;),return语句,if,switch,while或do-while语句的控制表达式,以及for语句中的所有三个表达式.在函数调用中输入函数之前.未指定参数的计算顺序,但此序列点表示在输入函数之前所有副作用都已完成.在表达式中
f(i++) + g(j++) + h(k++),f使用原始值的参数调用i,但i在进入正文之前递增f.同样,j和k正在进入前更新g和h分别.然而,不指定以何种顺序f() …
我有一个使用floats或doubles执行一些计算的算法.
例:
double a;
double b;
double c;
...
double result = c / (b - a);
if ((result > 0) && (result < small_number))
{
// result is relevant...
} else {
// result not required...
}
Run Code Online (Sandbox Code Playgroud)
现在,我担心(b - a)可能是零.如果它接近于零而不是零,则无关紧要,因为result它将超出范围是有用的,并且我已经检测到(当(b - a)接近零时,result将接近+/- inf,这不在范围内0- small_number. ..)
但如果结果(b - a)恰好为零,我预计由于除以零而会发生某种平台依赖.我可以将if声明更改为:
if ((!((b-a) == 0.0)) && ((result = c/(b-a)) > 0) && (result …Run Code Online (Sandbox Code Playgroud) 注意:这是一个自我问答,并且针对“Let us C”一书宣传的错误信息进行了更直观的提问。另外,请让我们不要讨论C++,这个问题是关于 C 的。
我正在阅读 Yashwant Kanetkar 的书“Let us C”。
书中有如下例子:
#include <stdio.h>
int main(void) {
int a = 1;
printf("%d %d %d", a, ++a, a++);
}
Run Code Online (Sandbox Code Playgroud)
作者声称这段代码应该输出3 3 1:
令人惊讶的是,它输出
3 3 1. 这是因为 C 的调用约定是从右到左。也就是说,首先1通过表达式a++,然后a增加到2。然后结果++a就通过了。即 a 增加到 3 然后通过。最后,传递 a 的最新值,即 3。因此按从右到左的顺序1, 3, 3通过。一旦printf( ) 收集它们,它就会按照我们要求它打印它们的顺序(而不是传递它们的顺序)打印它们。这样3 3 1就打印出来了。
但是,当我编译代码并使用 运行它时clang,结果是1 2 2 …
c undefined-behavior sequence-points language-lawyer order-of-execution
为什么以下打印出"World Hello!"?
根据我的理解,根据运算符优先级,这应该从右边开始评估.但相反,从左到右似乎是正确的.为什么是这样?
#include <iostream>
using namespace std;
char print() {
cout << "World";
return '!';
}
int main() {
cout << "Hello " << print() << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 请查看以下代码段:
int a = 10, b;
b = (a) + (++a); //2
printf("b = %d\n", b);
Run Code Online (Sandbox Code Playgroud)
输出:
b = 22
Run Code Online (Sandbox Code Playgroud)
在声明2中,有4个不同的运算符.其中()优先级最高.由于()操作员的关联性是从左到右为什么b = 22而不是21?
$ gcc --version
gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
Run Code Online (Sandbox Code Playgroud) 因此,通过查询所有内容并了解std库函数的行为来学习C,我遇到了这样的:
在以下2个代码中;
代码1:
#include <stdio.h>
int main()
{
printf(" %d %d",printf("Hello"),printf("Bye"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
ByeHello 5 3
代码2:
#include <stdio.h>
int main()
{
printf(" %d",printf("Hello")+printf("Bye"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
HelloBye 8
在第一个计划中; 表达式似乎是从右到左执行,但在第二个代码中,表达式从左到右执行.为什么会这样呢?表达式是如何执行的?
我写了一个简单的函数如下......
int fun(int *i, int *j)
{
*i += 3;
*j += *i;
return (*i + *i);
}
Run Code Online (Sandbox Code Playgroud)
在主函数中,我将函数调用如下...
int main()
{
int x = 3, y = 2, a, b;
a = x + y + fun(&x, &y) + x;
b = y + fun(&x, &y) + y;
cout<<" a = " << a << "\n";
cout<<" b = " << b << "\n";
}
Run Code Online (Sandbox Code Playgroud)
现在问题是输出不如预期
运行后这是输出
a=23
b=52
Run Code Online (Sandbox Code Playgroud)
我在期待
a=23
b=46
Run Code Online (Sandbox Code Playgroud)
我不知道究竟是否有人可以解释.
我有一个代码。代码打印1236(g++ 7.5.0)
输出取决于编译器吗?(例如输出可以是3216)
#include <bits/stdc++.h>
using namespace std;
int foo(int& x) {
std::cout << ++x;
return x;
}
int main() {
int i = 0;
cout << foo(i) + foo(i) + foo(i) << endl; // 1236
}
Run Code Online (Sandbox Code Playgroud)