我刚开始学习C语言,我了解到
*a = *b;
a++;
b++;
和
*a++ = *b++
这两个表达式是等价的,但这确实是当这行代码被执行时发生的事情吗?
*a++ = *b++
这被称为什么?有人能澄清编译器如何解释第二行吗?我知道右到左的优先级等等,但有人能精确地写出编译器用于解释这行代码的步骤吗?
You said that you believe that:
*a = *b; a++; b++;
等同于
*a++ = *b++;
但那是错误的,所以你持有错误的信念。让我们纠正你的错误信念。
在第一个情况下,必须发生以下事情:
*a
以产生一个变量,称之为var
*b
以产生一个值,称之为val
val
分配给var
a
b
编译器如何安排这些的约束条件?
规则是语句的所有副作用必须在下一条语句开始之前完成。因此,存在两种合法的排序。VAR VAL ASSIGN INCA INCB或VAL VAR ASSIGN INCA INCB。
现在让我们考虑第二种情况。
*a++ = *b++;
我们有相同的五个操作,但它们的顺序约束完全不同,因为它们都在同一语句中,所以关于语句的规则不适用。现在的约束条件是:
a
的原始值b
的原始值var = a;
a = a + 1; // increment a before assign
*var = *b;
b = b + 1; // increment b after assign
这样做也是合法的:
val = *b;
b = b + 1; // increment b before assign
*a = val;
a = a + 1; // increment a after assign
按照您的建议执行任务,先进行赋值操作,然后按从左到右的顺序增加两个操作数,也是合法的。以及,先进行赋值操作,然后按从右到左的顺序增加两个操作数,也是合法的。
C编译器有广泛的自由度来生成此类表达式的代码。请确保你已经非常清楚了解这一点,因为大多数人都会弄错:仅仅因为++
出现在变量后面并不意味着增量晚发生。编译器可以在任何时候进行增量操作,只要编译器确保使用了原始值即可。
这是C和C++的规则。在C#中,语言规范要求赋值左边的副作用先于赋值右边的副作用,并且两者都要在赋值的副作用之前发生。相同的代码在C#中将被要求生成如下:
var_a = a;
a = a + 1;
// must pointer check var_a here
var_b = b;
b = b + 1;
val = *var_b; // pointer checks var_b
*var_a = val;
"指针检查"是指C#要求运行时验证var_a
是否为有效的指针的点;换句话说,即确认*var_a
实际上是一个变量。如果不是,则必须在评估b
之前抛出异常。
同样,C编译器可以采用C#的方式进行,但并非必须。
a=*p++
有两种执行方式 (1) 首先将 p
赋值给某个 VAR,然后因为 ++
的优先级更高,所以 p
更新为指向下一个位置,然后在 第二步 中,将 p
的旧值 = VAR 分配给 a
,即 a=*VAR
。**(2)** 首先将 *p
赋值给 a
,因为 ++
是后缀运算符,然后 p
更新为指向下一个位置。 - Grijesh Chauhanp
增量的副作用,接着发生对旧值p
解引用的副作用(请记住,在C#中,如果指针无效,则解引用会产生副作用),最后发生赋值的副作用。也就是说,在C#中,子表达式的副作用从左到右发生,运算符的优先级顺序为准。 - Eric Lipperta = *P++
可以像 var = p;
p = p + 1;
a = *var
一样被求值! - haccks1)
*a = *b;
a++;
b++;
等同于
*a = *b;
a = a+1;
b = b+1
2)
x = *a++
等同于
x = *a;
a = a+1;
*b++ = x
等同于
*b = x;
b = b+1;
so
*a++ = *b++
等同于
*a = *b;
a = a+1;
b = b+1
3)
*(++a) = *(++b)
等同于
a = a+1;
b = b+1
*a = *b;
gcc -S
生成的汇编代码。 - Grijesh Chauhan*a++ = *b++;
中,++
是后缀操作符。因此,首先将*b
赋值给*a
,然后执行b++
和a++
。 - Grijesh ChauhanA() + B() * C()
时,并不要求B()
和C()
必须在A()
之前调用,仅仅因为*
的优先级比+
高。只要在*
之前调用B()
和C()
,在+
之前调用A()
,在*
之前调用+
,函数可以以任何顺序被调用。编译器可以选择满足这些约束条件的任何调用顺序。 - Eric Lippert