为什么这样子啊?
#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 %d\n", w++, ++w, w); // shouldn't this print 0 2 2
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++);
是未定义行为的一个典型例子
只需编译和反汇编你的代码行,如果你很想知道它到底是什么
下面是我看到的,以及我认为正在运行的:
$ cat evil.cvoid evil(){
int i = 0;
i+= i++ + ++i;}
$ gcc evil.c -c -o evil.bin
$ gdb evil.bin(gdb) disassemble evilDump of assembler code for function evil:
0x00000000 <+0>: push %ebp
0x00000001 <+1>: mov %esp,%ebp
0x00000003 <+3>: sub $0x10,%esp
0x00000006 <+6>: movl $0x0,-0x4(%ebp) // i = 0 i = 0
0x0000000d <+13>: addl $0x1,-0x4(%ebp) // i++ i = 1
0x00000011 <+17>: mov -0x4(%ebp),%eax // j = i i = 1 j = 1
0x00000014 <+20>: add %eax,%eax // j += j i = 1 j = 2
0x00000016 <+22>: add %eax,-0x4(%ebp) // i += j i = 3
0x00000019 <+25>: addl $0x1,-0x4(%ebp) // i++ i = 4
0x0000001d <+29>: leave
0x0000001e <+30>: retEnd of assembler dump.