关于评价顺序和比较的几个问题
some questions about evaluation order and comparison
在一次C/c++面试测试中,我发现一些问题我没有正确回答,我用Visual c++检查了一下结果,希望您能帮助我理解:
1)
int i=-3, j=2, k=0, m;
m = ++i && ++j || ++k; // k not incremented why ???
cout << i << " " << j << " " << k << " " << m; // -2 3 0 1 why it's not -2 3 1 1 !!!
=>为什么k不加,特别是在它前面有一个++ ?我想知道执行这一行的顺序,我不能在调试模式下这样做。
你能给我一个规则来评估这样的表达式,其中有东西像++变量或变量++谢谢你
2)为什么这个比较是错误的?
float a = 5.2;
if(a == 5.2) // false
{}
当我添加一个浮点转换到5.2它工作....
3)
int n()
{
static int x = 0;
return x++;
}
=>我认为我们总是返回0,因为我认为编译器会将"return x++"翻译为:x + +;那么我们将永远不会执行增量…
问题1:
&&
运算符优先于||
,因此它将首先求值。++i
和++j
两项都有预增量,所以先将它们分别增加到-2和3,然后对它们进行and。在c++中,0是false
,其他都是true
。在本例中,两个项都是true
(即非零),因此&&
返回true
。现在是测试true || ++k
的时候了。这里,一个优化开始了:因为true || anything
总是true
,编译器甚至不测试表达式。也就是说,它不会执行它。k
不加1。这就是为什么让if语句中的代码做一些事情是一个非常坏的习惯——你不能确定它是否会运行,这取决于条件。如果需要来运行,请确保它没有放在那里,否则它可能会被优化掉。
问题2:
浮点运算很棘手——准确地表示一个数字通常是不可能的,而真正使用的数字只是一个非常接近的近似值——接近到看起来可以工作,但如果你检查每一个小的地方,你会发现数字并不是它们看起来的样子。默认情况下,数字被视为double
。一个double
和一个float
,虽然它们看起来一样,但并不相同。这里已经讨论过了:float和float literal比较时的奇怪输出。我强烈建议大家阅读其中一篇链接文章,这篇:《每个计算机科学家都应该知道的浮点算术》
问题3:
你是对的,返回值是0(第一次!),但是你认为该指令被分成两部分,其中第一部分是return
,这应该导致第二部分(增量)被跳过。不,不是这样的。在任何情况下都执行增量。后增量的工作原理是这样的:创建一个副本,增加原始副本,返回副本。不管叫后增量的是什么,都会看到原始值,但是增量不会发生。并且由于x
是static
,因此该值将被保留,因此下次调用n()
函数时,x
的初始值将为1。然后是2 3,等等
下次,当你有多个问题时,请分开问。
问题1的答案:
几件事情:
-
&&
和||
运算符都强制从左到右求值1,并且都引入了序列点;在计算右操作数之前,将计算左操作数,并应用所有副作用; -
&&
和||
操作符都短路——如果表达式的值可以从左侧操作数确定,则不计算右侧操作数;- 表达式
- 如果
a
非零则不求值; 表达式 - ,如果
a
为零,则不计算b
;
a || b
、b
中的a && b
中的 - 如果
-
&&
优先级高于||
,因此a || b && c
解析为a || (b && c)
; -
x++
计算x
的当前值,并且作为副作用使x
增加; -
++x
计算x
的当前值加1,并且作为副作用使x
增加。
表达式
++i && ++j || ++k
被解析为
(++i && ++j) || ++k
和对求值如下:
-
++i
被评估;结果是-2
,它不是零,所以: -
++j
被评估;结果是3
,所以: -
-2
和3
都是非零,所以: -
++i && ++j
求值为1,因此: -
++k
根本不被评估。
问题2的答案:
还有几个问题:
大多数浮点值不能精确地表示;它们以近似值的形式存储(你不能将无限数量的值放入有限数量的比特中);
浮点常量表达式
5.2
的类型是double
,而不是float
;要使它成为float
,您将使用f
后缀-5.2f
;float
和double
具有不同的表示(double将更多的位用于指数和分数),因此它们将为相同的值存储不同的近似值,这就是==
比较不起作用的原因。正因为如此,你不应该使用
==
来比较浮点值;通常,你会取两个值之间的差,并确保它小于某个值(记住,值取决于大小)。
问题3的答案:
您正在返回表达式 x++
的结果,但是该表达式仍然具有增加x
的副作用(并且该副作用在return
语句结束之前应用)。
<一口> 1。C语言中的大多数运算符不强制执行特定的求值顺序——给定一个像
a + b * c
这样的表达式,a
、b
和c
中的每一个都可以按任意顺序求值。必须知道b * c
的结果才能将其添加到a
的结果中,但这并不意味着b
或c
必须在a
之前求值。一口>
- C和c++操作短路逻辑。
考虑以下内容:
bool myBool = (1 || 0+6*4);
myBool
将尽快计算。在本例中,它的值为true,因为||
中的左参数为true。它立即停止计算。&&
也是如此。这就是为什么习惯地在布尔运算符的左侧添加更有可能失败的情况。
- 为false,因为浮点数不能完美地用二进制表示。
在这种情况下,它的值实际上是true。但是,请考虑以下示例:
#include <iostream>
int main() {
double i = 0.1;
double total = 0.0;
for(int j = 0; j < 10000; j++) {
total+=i;
}
// total = 0.1*10000 = 1000... right?
std::cout << std::boolalpha << "total == 1000.0 ? " << (total == 1000.0) << std::endl;
return 0;
}
下面是上面程序的输出。比较浮点数和双精度数在计算中是一件棘手的事情。做这件事要小心。
- 因为它是静态的,它将在返回之前递增,并且每次调用函数时保持其静态值。
我不会深入讨论这个问题,因为它在静态变量生命周期的问题中已经很好地概述了。本质上,static
与程序一样存在,而不考虑可见性
- 为我的 c++ 类介绍制作一个三角形分类器.我有几个问题
- 关于 std::bitset 构造函数的几个问题?
- 分发我自己的程序的几个问题
- 关于Qt的几个问题
- 关于SDL_Window和unique_ptr的几个问题
- 关于C++内联函数的几个问题
- 我正在尝试[C++]练习多态性和OOD原则。需要指导和几个问题的答案
- 关于C++中数组的几个问题
- 我是C++新手,我有几个问题想问
- C++ - 关于引发异常的几个问题
- 选择-几个问题
- 在Windows上编译和运行示例c++程序的几个问题
- ReadFileEx,可变长度-几个问题
- c++中虚方法表的几个问题
- 关于评价顺序和比较的几个问题
- 关于类成员指针的几个问题
- 模板类——几个问题
- Qt(C++)的几个问题
- QtCreator的几个问题
- 关于声明语义的几个问题