请考虑:
char *s, *t;
char c;
这项任务会发生什么?
*t++ = *s++;
这在功能上是否等同于(选项1):
c = *t;
t++;
*s = c;
s++;
或者,它是否等同于此(选项2):
c = *s;
s++;
*t = c;
t++;
请考虑:
char *s, *t;
char c;
这项任务会发生什么?
*t++ = *s++;
这在功能上是否等同于(选项1):
c = *t;
t++;
*s = c;
s++;
或者,它是否等同于此(选项2):
c = *s;
s++;
*t = c;
t++;
*ptr
和*ptr++
在C中是惯用的,
但是为了非常清楚地说明*
是具有单个操作数的一元运算符,
我将继续将该操作数写在括号中.
那么让我们考虑一下*(ptr)
和*(ptr++)
.
对于运算符*
,我们给它什么表达式并不重要.
重要的是它的运算数的return value,
因为这是正在读取数据(赋值的右操作数)或写入数据(赋值的左操作数)的地址.
ptr++
和ptr
具有the same个返回值(在判断之前给定相同的内存状态).
因此,*(ptr++)
的行为与*(ptr)
的行为相同.
唯一的区别是ptr++
的side effect:指针值是递增的.
但这种副作用既不会影响返回值ptr++
,也不会影响*
的运算.
我总是想象后递增发生在声明的末尾,但这只是我的心理模型.
无论出于什么原因(通常是性能提升),编译器may决定更早地递增ptr
;
只要净效果是一样的.
所以任何包含*(ptr++)
的C语句基本上都等同于包含*(ptr)
的相同语句,
之后是附加语句ptr++;
.
这甚至适用于多个变量后递增的情况,如您的示例所示:
*t++ = *s++;
等同于:
*t = *s;
t++;
s++;
当同一指针变量在语句中出现两次时,事情就变得棘手了. 这通常是未定义的行为(UB), 因为同一语句中(子)表达式的求值顺序在C中大部分是未定义的(除了少数操作符).
*s++ = *s++;
not(保证)等同于:
*s = *s;
s++;
s++;