C语言的副作用

测试例子1:

#include 

int main(void) {
  int a = 5;
  printf("%d, %d, %d\n", (a++) , (a++) , (a++));
  printf("a = %d\n", a);
  return 0;
}

编译执行:

$ gcc foo.c
$ ./a.out 
7, 6, 5
a = 8

测试例子2:

#include 

int main(void) {
  int a = 5;
  printf("s = %d\n", (a++) + (a++) + (a++));
  printf("a = %d\n", a);
  return 0;
}

编译执行:

$ gcc-4.7 foo.c
$ ./a.out 
s = 15
a = 8
$ gcc-4.8 foo.c
$ ./a.out 
s = 18
a = 8

原因在于C语言标准中关于side effect和sequence point的描述和规范。这里有篇博文,介绍的非常到位(多谢kito-cheng提供)http://blog.tinlans.org/2010/08/06/sequence-point/

C语言标准中的原文如下:

The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.) See the discussions of additive operators and compound assignment
for information on constraints, types, and conversions and the effects of operations on
pointers. The side effect of updating the stored value of the operand shall occur between
the previous and the next sequence point.
Evaluation of an expression may produce side effects. At
certain specified points in the execution sequence called sequence points, all side effects
of previous evaluations shall be complete and no side effects of subsequent evaluations
shall have taken place.

gdb无法调试最新gcc编译的程序

Reading symbols from /home/foo/helloword...done.
(gdb) start
Temporary breakpoint 1 at 0x4004dc
Starting program: /home/foo/helloword 

Temporary breakpoint 1, 0x00000000004004dc in main ()
(gdb) n
Single stepping until exit from function main,
which has no line number information.
Hello World
__libc_start_main (main=0x4004d8 
, argc=1, ubp_av=0x7fffffffc2b8, init=, fini=, rtld_fini=, stack_end=0x7fffffffc2a8) at libc-start.c:258 258 exit (result); (gdb)

这里,gcc是较新的版本,gdb版本较旧。原因是因为,gcc从4.8开始缺省使用了-gdwarf-4选项,较旧的gdb无法识别dwarf4版本的调试信息(多谢jasonwucj的指点)。参见

https://gcc.gnu.org/gcc-4.8/changes.html

当无法更新gdb的时候,则可以在用gcc编译程序时,使用选项-gdwarf-3来指定生成dwarf3版本的调试信息,这样就可以了。