相关疑难解决方法(0)

序列点和运算符优先级之间有什么区别?

考虑经典序列点示例:

i = i++;
Run Code Online (Sandbox Code Playgroud)

C和C++标准声明上述表达式的行为未定义,因为=运算符与序列点无关.

让我感到困惑的是,++优先级高于优先级=,基于优先级的上述表达式必须首先进行评估i++然后进行赋值.因此,如果我们开始i = 0,我们应该总是i = 0(或者i = 1,如果表达式i = ++i)结束而不是未定义的行为.我错过了什么?

c c++ language-lawyer

27
推荐指数
2
解决办法
631
查看次数

谁定义了C运算符优先级和关联性?

介绍

在C/C++的每本教科书中,您都可以找到运算符优先级和关联表,如下所示:

运算符优先级和关联表

http://en.cppreference.com/w/cpp/language/operator_precedence

StackOverflow上的一个问题是这样的:

以下函数的执行顺序如下:

f1() * f2() + f3();
f1() + f2() * f3();

参考上面的图表,我自信地回答说函数具有从左到右的关联性,因此在前面的语句中,在这两种情况下都会像这样评估:

f1() - > f2() - > f3()

评估函数后,您完成评估,如下所示:

(a1*a2)+ a3
a1 +(a2*a3)

令我惊讶的是,很多人告诉我,我错了.决心证明他们错了,我决定转向ANSI C11标准.我再一次惊讶地发现在运算符优先级和关联性方面提到的很少.

问题

  1. 如果我认为函数总是从左到右进行评估是错误的,那么表中涉及函数优先级和关联性的真正含义是什么?
  2. 谁定义了运算符优先级和关联性,如果它不是ANSI?如果是ANSI的定义,为什么很少提到运算符优先级和关联性?运算符优先级和关联性是从ANSI C标准推断还是在数学中定义?

c c++ operator-precedence associativity ansi-c

26
推荐指数
3
解决办法
8249
查看次数

初学者需要简单说明评估顺序与优先/关联性之间的区别

我正在阅读《 K&R》第二章的结尾,我在理解两个特定的不相关示例代码行(及其后)以及本书的注释时遇到一些困难:

x = f() + g();
a[i] = i++;
Run Code Online (Sandbox Code Playgroud)

第一线 -我很容易理解该标准未指定+运营商的评估顺序,因此未指定是先评估f()还是g()先评估(这就是为什么我认为这个问题不是重复的)。我的困惑源于以下事实:如果我们查找C运算符优先级图表,就会引用具有从左到右的关联性的最高优先级的函数调用。现在,这f() 是否意味着必须先调用/评估g()?显然不是,但是我不知道自己缺少什么。

第二行 -关于数组是索引到的初始值i还是递增的值,同样存在类似的难题。但是,运算符优先级图表再次引用了具有左至右关联性的最高优先级的数组下标。因此,数组下标不是导致将数组下标到的初始值i并消除任何歧义的第一要评估的东西吗?显然不是,我缺少了一些东西。

我确实知道编译器可以自由决定表达式中何时发生副作用(当然是在序列点之间),并且如果在同一表达式中再次使用有问题的变量,可能会导致不确定的行为,但是在上面的示例中似乎任何歧义都可以通过函数调用和具有最高优先级并定义了从左到右的关联性的数组下标来清除,因此我看不到歧义。

我感觉我对关联性,运算符优先级和评估顺序有一些基本的误解,但我无法指出它是什么,与此主题相关的类似问题/答案不在我的支持范围之内。在这一点上彻底了解。

c

26
推荐指数
3
解决办法
1607
查看次数

为什么运算符`?:`没有优先权?

调试后我发现三元运算符?:没有优先级.我的问题是为什么?
我有以下代码:

bool T = true;
cout << ((T == true) ? "true" : "false") << endl;
cout << (T == true) ? "true" : "false";
Run Code Online (Sandbox Code Playgroud)

输出:

true
1
Run Code Online (Sandbox Code Playgroud)

现场演示:http://ideone.com/Tkvt9q

c++

24
推荐指数
4
解决办法
2471
查看次数

操作数的评估顺序

在表达式中a + b,a保证在之前进行评估b,还是未指定评估的顺序?我认为这是后者,但我很难在标准中找到明确的答案.

由于我不知道C是否处理与C++有所不同,或者如果在C++ 11中简化了评估顺序规则,我将把这个问题标记为三个.

c c++ expression operator-precedence c++11

13
推荐指数
2
解决办法
3936
查看次数

运算符优先级 - 表达式评估

对于以下代码片段,我得到输出为1.我想知道它是怎么来的?

void main()
{
int x=10,y=20,z=5,i;
i=x<y<z;
printf("%d",i);
}
Run Code Online (Sandbox Code Playgroud)

c operator-precedence

8
推荐指数
1
解决办法
1884
查看次数

序列点与运算符优先级

可能重复:未
测序的值计算(也称为序列点)
未定义的行为和序列点
运算符优先级与评估顺序

我仍然试图围绕以下表达式如何导致未定义的行为:

a = a++;
Run Code Online (Sandbox Code Playgroud)

在搜索SO时,我发现了以下问题:

序列点和运算符优先级之间的差异?0_o

我仔细阅读了所有答案,但我仍然对细节有困难.其中一个答案描述了我的上述代码示例的行为在a修改方面是不明确的.例如,它可以归结为以下任何一种:

a=(a+1);a++;
a++;a=a;
Run Code Online (Sandbox Code Playgroud)

究竟什么使a修改变得模棱两可?这是否与不同平台上的CPU指令有关,以及优化器如何利用未定义的行为?换句话说,由于生成的汇编程序,它似乎未定义?

我没有看到编译器使用的原因a=(a+1);a++;,它只是看起来古怪而且没有多大意义.什么会让编译器使它以这种方式运行?

编辑:

为了清楚起见,我确实理解正在发生的事情,我只是不明白当有关于运算符优先级的规则(它基本上定义了表达式的求值顺序)时它是如何被定义的.在这种情况下,赋值最后发生,因此a++需要首先进行评估,以确定要分配的值a.所以我期望的是a,在修复后增量期间首先修改,但随后产生一个值以分配回a(第二次修改).但运算符优先级的规则似乎使我的行为非常清楚,我没有找到任何"摆动空间",因为它有未定义的行为.

c++ sequence-points

7
推荐指数
1
解决办法
581
查看次数

为什么大多数语言都没有优化"0*...",是否有任何语言可以做到?

我正在编写一个2D曲线算法并且有一些代码可以有效地进行求和a la:

for (i=0, end=...; i<end; i++) {
  value += coefficients[i] * expensiveToCalculateValue(i);
}
Run Code Online (Sandbox Code Playgroud)

coefficients[i]某些迭代步骤的值为零.由于零次仍然为零(至少在简单的算术规则下),我认为我可以通过首先检查是否coefficients[i]为零来显着优化此代码,如果是,则仅对continue下一次迭代.添加,排序,工作出色.

但这留下了一个问题:为什么这不适合我呢?这不是一些创造性的小众乘法版本,它是简单的算术.实际上所有语言都会使二进制OR和AND操作短路,如果找到一个操作数使得该结果从该点开始不变,那么为什么算术乘以零不会同样短路?

我尝试用Java,PHP,JavaScript,Perl,Python,C++运行这段代码(为synax修改),甚至看看Prolog做了什么,但没有人意识到一旦他们看到"零次......"他们不必评估潜在的昂贵的第二(或第三,第四等)术语:

printed = 0;
function veryExpensive() {
  print "oh god this costs so much, x" + (printed++);
  return 0;
}
value = 0 * veryExpensive() * veryExpensive() * veryExpensive()
Run Code Online (Sandbox Code Playgroud)

所有这些人最终都跑veryExpensive()了三次.

现在,我明白你可以 - 如果你是那种人 - veryExpensive根据你可以依赖它执行的事实来编写你的函数来执行管理开销工作,尽管它的结果没有对算术表达做出贡献(如果你做的话)那,你可能会滥用一种语言,但是在编程生涯中,每个人都喜欢鬼鬼祟祟的忍者代码),但是你只是这样做,因为你知道语言恰好在这种情况下无法优化.如果语言为您优化了算术评估,那么您的代码表达性就不会受到严重影响.

那么:是否有一些历史先例导致当前使用的大量语言优化为"真正的OR ......"和"假的......"而不是"零时间......"?为什么我们优化二进制操作,而不是MUL 0?(如果我们很幸运,有人会有一个引人入胜的故事,告诉我们为什么现在不要短路)

更新

约翰斯基特和尼克布加利斯都提出了很好的论据,为什么用现存的语言来优化这个问题会导致问题,但是尼克的回答更加符合这个问题,所以我将他的答案标记为"正确的".也就是说,它们涵盖了同一问题的不同方面,因此真正的答案是两者的结合.

language-agnostic syntax optimization

6
推荐指数
2
解决办法
192
查看次数

运算符优先级和评估顺序

我无法理解这个程序的输出:

#include<iostream>
using namespace std;
int main()
{
    int x = 1 , y = 1, z = 1;
    cout << ( ++x || ++y && ++z ) << endl; //outputs 1;
    cout << x << " " << y << " " << z ;  //x = 2 , y = 1 , z = 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
2 1 1
Run Code Online (Sandbox Code Playgroud)

如果||被评为第一,然后这个输出是好的,但是这个文章说,&&比一个更高的优先级||,因此必须首先评估.如果是这种情况那么根据我的输出应该是:

1
1 2 2
Run Code Online (Sandbox Code Playgroud)

++y …

c++ operators operator-precedence output

6
推荐指数
3
解决办法
671
查看次数

括号和逻辑运算符

考虑这段代码(C++):

int x = -4 , y = 5 ;
bool result = x > 0 && y++ < 10 ;
Run Code Online (Sandbox Code Playgroud)

表达式(X> 0)将被首先计算,并且因为(X> 0 =假),并且由于短路评价,其他表达(Y ++ <10)将不会被评价和y的值将保持5 .

现在考虑以下代码:

int x = -4 , y = 5 ;
bool result = (x > 0) && (y++ < 10) ;
Run Code Online (Sandbox Code Playgroud)

可以预期,在括号中的表达式将被首先计算,使得逻辑AND被执行时,表达之前(Y ++ <10)将已被评估和y的值已成为6,但现实情况是,y的值仍然是5.这意味着即使使用括号,评估也会被短路,并且忽略表达式(y ++ <10).

这个案子有什么解释?

c++ java short-circuiting logical-operators

4
推荐指数
1
解决办法
2932
查看次数