关于# define 的一个有关问题

关于# define 的一个问题
在Turbo C中编译下面的程序:
#define pro(x) (x*x)
void main(void)
{
  int i=3,j,k;
  j=pro(i++);
  k=pro(++i);
  printf("j=%d,k=%d",j,k);
}
  define相当于在编译前直接将字符替换,那么按照我的理解就是j=(i++)*(i++);因为是后置++,则前面一项为3代入运算,++后i=4,后面一项就应该为4代入运算,++后i=5,则j=3*4=12;
k=(++i)*(++i),前面一项为5+1=6,带入运算且此时的i=6,后面一项6+1=7带入运算且此时的i=7,计算结果为6*7=42
  但是运行之后的结果是9、49,为什么呢?期盼解答,多谢~

------解决方案--------------------
和编译处理有关

------解决方案--------------------
shuijing8419:
第一,j=(i++)*(i++)是不准确的,define的宏的一个特点就是仅仅是替换,它是不会自动加上括号的。
因此本题应该替换结果为:j=i++*i++;由于
第二,j=i++*i++中谁先算运算结果是不固定的.这个应该属于order of evaluation 的范畴。
------解决方案--------------------
我在VC6.0中也试了,也是9和49
改成#define pro(x) ((x)*(x)) 
也是同样的输出
不管怎么变得出的结果肯定是一个数的平方
也就是说i++*i++时,是用i乘完以后,再将i进行两次++运算
如果是++i*++i,是将i增加两次之后再用i相乘得到结果
int i = 3,j;
j = pro(++i);
cout<<j;

j = 25
------解决方案--------------------
上网查了:

编译器的跨序列点优化
根据前述讨论可知,在同一个表达式内对于同一个变量i,允许的行为是
A. 不读取,改写一次,例如
i = 0;
B. 读取一次或者多次,改写一次,但所有读取仅仅用于决定改写后的新值,例如
i = i + 1; // 读取一次,改写一次
i = i & (i - 1); // 读取两次,改写一次,感谢puke给出的例子
C. 不改写,读取一次或者多次,例如
j = i & (i - 1);

因此在同一个表达式中对同一变量修改多次是没有意义的(其实写法就是错误的)
由此可见,常见的问题如printf("%d, %d", i++, i++)这种写法是错误的,这类问
题作为笔试题或者面试题是没有任何意义的