我正在读这个问题:
并且,特别是C++ 11的答案,我理解评估的"排序"的想法.但是 - 写作时是否有足够的顺序:
f(x++), g(x++); ?
也就是说,我保证f()获得原始值x并g()获得一次递增x?
挑剔的注意事项:
operator++()已定义的行为(即使我们已经重写它),这样做f()和g(),没有异常将被抛出,等-这个问题是不是有关.operator,()没有超载.我一直在寻找更多适合的习语std::exchange。
今天我发现自己在一个答案中写下了这个:
do {
path.push_front(v);
} while (v != std::exchange(v, pmap[v]));
Run Code Online (Sandbox Code Playgroud)
我比说更喜欢它
do {
path.push_front(v);
if (v == pmap[v])
break;
v= pmap[v];
} while (true);
Run Code Online (Sandbox Code Playgroud)
希望有明显的原因。
然而,我对标准语言并不热衷,我不禁担心这并lhs != rhs不能保证右侧表达式在左侧表达式之前没有被完全求值。这将使其成为同义反复的比较 - 根据定义将返回true.
然而,代码确实运行正确,显然lhs首先进行评估。
有人知道吗
附言。f(a,b)我意识到这是where fis的一个特例operator!=。我尝试使用此处找到的信息回答我自己的查询,但迄今为止未能得出结论:
可能重复:
为什么会进入无限循环?
类似于i = i++C和C++中的未定义行为,因为标量对象的值在同一表达式中更改两次而没有插入序列点.
但是我认为这些表达式在C#或Java中具有明确定义的行为,因为AFAIK对参数的评估从左到右,并且全部都有序列点.
那就是说,我希望i = i++相当于i++.但事实并非如此.以下程序输出0.
using System;
class Program
{
static void Main(string[] args)
{
int i = 0;
i = i++;
Console.WriteLine(i);
}
}
Run Code Online (Sandbox Code Playgroud)
你能帮我理解为什么吗?
免责声明: 我完全清楚,无论是否定义了上述结构的行为,它们都是愚蠢,无用,不可读,不必要的,不应在代码中使用.我只是好奇.
正如先前建立的,形式的联合
union some_union {
type_a member_a;
type_b member_b;
...
};
Run Code Online (Sandbox Code Playgroud)
与Ñ成员包括Ñ在重叠存储+ 1对象:联合本身一个目的并且对于每个联盟成员一个对象.很明显,您可以按任何顺序自由地读取和写入任何工会成员,即使读取的工会成员不是最后写入的工会成员.永远不会违反严格别名规则,因为访问存储的左值具有正确的有效类型.
脚注95 进一步支持了这一点,脚注95解释了类型双关语是否是联盟的预期用途.
严格别名规则启用的优化的典型示例是此函数:
int strict_aliasing_example(int *i, float *f)
{
*i = 1;
*f = 1.0;
return (*i);
}
Run Code Online (Sandbox Code Playgroud)
编译器可能会优化到类似的东西
int strict_aliasing_example(int *i, float *f)
{
*i = 1;
*f = 1.0;
return (1);
}
Run Code Online (Sandbox Code Playgroud)
因为它可以安全地假设写入*f不会影响值*i.
但是,当我们将两个指针传递给同一个联盟的成员时会发生什么?考虑这个例子,假设一个典型的平台float是IEEE 754单精度浮点数,并且int是32位二进制补码整数:
int breaking_example(void)
{
union {
int i;
float f;
} fi;
return (strict_aliasing_example(&fi.i, &fi.f));
} …Run Code Online (Sandbox Code Playgroud) 命令式编程中的序列点定义了计算机程序执行中的任何点,在该点处保证先前评估的所有副作用都已执行,并且尚未执行后续评估的副作用.
这是什么意思?有人可以用简单的语言解释一下吗?
我正在阅读《 K&R》第二章的结尾,我在理解两个特定的不相关示例代码行(及其后)以及本书的注释时遇到一些困难:
x = f() + g();
a[i] = i++;
Run Code Online (Sandbox Code Playgroud)
第一线 -我很容易理解该标准未指定+运营商的评估顺序,因此未指定是先评估f()还是g()先评估(这就是为什么我认为这个问题不是重复的)。我的困惑源于以下事实:如果我们查找C运算符优先级图表,就会引用具有从左到右的关联性的最高优先级的函数调用。现在,这f() 是否意味着必须先调用/评估g()?显然不是,但是我不知道自己缺少什么。
第二行 -关于数组是索引到的初始值i还是递增的值,同样存在类似的难题。但是,运算符优先级图表再次引用了具有左至右关联性的最高优先级的数组下标。因此,数组下标不是导致将数组下标到的初始值i并消除任何歧义的第一要评估的东西吗?显然不是,我缺少了一些东西。
我确实知道编译器可以自由决定表达式中何时发生副作用(当然是在序列点之间),并且如果在同一表达式中再次使用有问题的变量,可能会导致不确定的行为,但是在上面的示例中似乎任何歧义都可以通过函数调用和具有最高优先级并定义了从左到右的关联性的数组下标来清除,因此我看不到歧义。
我感觉我对关联性,运算符优先级和评估顺序有一些基本的误解,但我无法指出它是什么,与此主题相关的类似问题/答案不在我的支持范围之内。在这一点上彻底了解。
作为一个实验,我这样做了:
letters=['a','b','c','d','e','f','g','h','i','j','k','l']
for i in letters:
letters.remove(i)
print letters
Run Code Online (Sandbox Code Playgroud)
最后一次打印显示并非所有项目都被删除了?(每隔一个人).
IDLE 2.6.2
>>> ================================ RESTART ================================
>>>
['b', 'd', 'f', 'h', 'j', 'l']
>>>
Run Code Online (Sandbox Code Playgroud)
对此有何解释?如何重新编写以删除每个项目?
拿这三个C代码片段:
1) a = b + a++
2) a = b + a; a++
3) a = b + a, a++
Run Code Online (Sandbox Code Playgroud)
每个人都知道示例1是非常糟糕的事情,并且明确地调用未定义的行为.例2没有问题.我的问题是关于示例3.逗号运算符在这种表达式中是否像分号一样工作?2和3是等价还是3和1一样未定义?
具体来说,我正在考虑这个问题free(foo), foo = bar.这基本上与上述问题相同.我可以确定foo在重新分配之前被释放,或者这是一个明确的序列点问题吗?
我知道这两个例子都是毫无意义的,只使用分号并完成它就更有意义了.我只是出于好奇而问.
根据c ++标准,
i = 3;
i = i++;
Run Code Online (Sandbox Code Playgroud)
将导致未定义的行为.
如果它可以导致多个结果,我们使用术语"未定义的行为".但是在这里,i无论评价的顺序如何,最终的价值都是4,所以这不应该被称为"未指明的行为"吗?
我知道诸如x = x++ + ++x调用未定义行为之类的事情,因为变量在同一序列点内被多次修改。这在这篇文章中进行了彻底的解释为什么这些构造使用前增量和后增量未定义行为?
但是考虑像printf("foo") + printf("bar"). 该函数printf返回一个int,因此该表达式在这个意义上是有效的。但是+标准中没有规定运算符的求值顺序,所以不清楚这会打印foobar还是barfoo。
但我的问题是这是否也是未定义的行为。