#include <stdio.h>
int main(void)
{
int i = 0;
i = i++ + ++i;
printf("%d\n", i); // 3
i = 1;
i = (i++);
printf("%d\n", i); // 2 Should be 1, no ?
volatile int u = 0;
u = u++ + ++u;
printf("%d\n", u); // 1
u = 1;
u = (u++);
printf("%d\n", u); // 2 Should also be one, no ?
register int v = 0;
v = v++ + ++v;
printf("%d\n", v); // 3 (Should be the same as u ?)
int w = 0;
printf("%d %d\n", ++w, w); // shouldn't this print 1 1
int x[2] = { 5, 8 }, y = 0;
x[y] = y ++;
printf("%d %d\n", x[0], x[1]); // shouldn't this print 0 8? or 5 0?
}
C有未定义行为的概念,即某些语言构造在语法上是有效的,但你无法预测代码运行时的行为。
据我所知,标准并没有明确地说为什么存在未定义行为的概念。在我看来,这仅仅是因为语言设计者希望在语义上有一定的回旋余地,而不是要求所有实现都以完全相同的方式处理整数溢出,这很可能会带来严重的性能代价,他们只是没有定义行为,这样如果您编写了导致整数溢出的代码,任何事情都可能发生。
那么,考虑到这一点,为什么这些是“问题”呢?语言明确地说,某些事情导致未定义的行为。没有问题,没有“应该”的牵扯。如果当一个涉及的变量声明为volatile
时未定义的行为发生了变化,那么这并不能证明或改变任何事情。未定义;你无法对这种行为进行推理。
你最有趣的例子是
u = (u++);
是一个未定义行为的教科书例子(参见维基百科关于序列点的条目)。
问题内容: 我最近为Eclipse安装了Checkstyle插件,并个人认为它很棒。但是它给我的警告之一有些晦涩。确切的警告是“ 不允许使用”。它是关于后缀在某行像 好的,我知道这是更好的迭代构造,但是它不能在所有地方都应用,有时老套是唯一的选择。 当我将行更改为 警告消失。我知道之间的区别,并和这一点我的生活我认为他们在标准的可互换建设。但是Checkstyle认为这是有害的(或容易出错)。 问
为什么这不会增加?我正在批处理文件中使用这个。它做任何事情都是正确的,只是没有增加。我做错了什么? 编辑:这不是重复,这是一个完全不同的问题。
问题内容: 我了解对此主题有很多疑问。但是我仍然有些困惑,不确定何时使用这些操作。我正在为参加考试而做的旧考试。其中一种方法返回可访问的残疾人可用教室的数量。我编写了counter方法,但不确定是应该先递增还是递后递增计数器。我对它如何与方法中的return语句混淆。我仍然不知道该方法将在下面返回什么值。其他问题未在方法中显示返回值,因此我对它的工作方式感到困惑。这是代码: 问题答案: 当您要在表
如果我有: 很明显,这个表达式后面的应该是零,但我看到的任何地方,他们都说这个代码的行为是未定义的,而不仅仅是的值(直到减法之前)。 很明显,编译器可以简单地在变量中使用它认为“方便”的任何垃圾值,并且它将按照预期工作。这种方法有什么问题?
问题内容: 我正在做一些有关Java的研究,发现这很令人困惑: 这是永无止境的循环! 有人很好地解释了为什么会发生这种事情吗? 问题答案: 上面的循环与以下内容基本相同:- 3 次你的一部分声明- ,被评估为: - 您需要从此处删除分配,以使其起作用:- (根据评论的OP请求) 的行为:- 就注释中指定的问题而言,以下表达式的结果:- 获得如下:- 让我们标记第二条语句的不同部分:- 现在,首先将
问题内容: 当我偶然发现名为JSpeed-Javascript优化的项目时,我正在浏览Google Code。 我注意到优化之一是更改为for循环语句。 优化之前 优化后 我知道前后的增量是什么,但是知道如何加快代码速度吗? 问题答案: 这是我阅读并可以回答你的问题:“前递增()加一的值,然后返回;相反,收益则增加了一个给它,这 _在理论上_中创建一个临时变量存储的值的结果在执行增量操作之前”。