关于 strcpy 函数的赋值语句
如何理解while (*s++ = *t++)
?
void strcpy(char *s, char *t)
{
while (*s++ = *t++);
}
该语句等价于while (*(s++) = *(t++))
。
赋值语句的结合方向是自右往左,所以从右往左读,可以将*(s++) = *(t++)
拆成两条语句:
temp = *(t++);
*(s++) = temp;
也即代码段 A:
temp = *t;
t++;
*s = temp;
s++;
赋值语句实际上是一个表达式,等于赋值运算符右边表达式的结果,比如a = b
的结果是b
。这里右边表达式是*(t++)
,结果是*t
(先使用,后自增),因此原代码可等价于代码段 B:
while (*t != '\0'){
*(s++) = *(t++);
}
代码段 A 和 B 结合在一起:
char temp = *t;
while (temp != '\0'){
temp = *t;
t++;
*s = temp;
s++;
}
需要提醒的是,平时不要写这样的代码,可读性较差。
一些汇编
*s++ = *t++
的汇编:
mov rdx, QWORD PTR [rbp-16] ; t 存入 rdx
lea rax, [rdx+1] ; t+1,然后存入 rax
mov QWORD PTR [rbp-16], rax ; rax 再压回栈中,供函数使用
mov rax, QWORD PTR [rbp-8] ; s 存入 rax
lea rcx, [rax+1] ; s+1,然后存入 rcx
mov QWORD PTR [rbp-8], rcx ; rcx 再压回栈中,供函数使用
movzx edx, BYTE PTR [rdx] ; rdx 所指向的内容即 *t 存入 edx
mov BYTE PTR [rax], dl ; edx 的低 8 位内容存入 rax 所指向的内容即 *s
strcpy 的汇编:
strcpy(char*, char*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi ; 以上均为调用函数前的操作,不用理会
.L3:
mov rdx, QWORD PTR [rbp-16] ; t 存入 rdx
lea rax, [rdx+1] ; t+1,然后存入 rax(rax = t+1)
mov QWORD PTR [rbp-16], rax ; rax 再压回栈中,供函数使用
mov rax, QWORD PTR [rbp-8] ; s 存入 rax
lea rcx, [rax+1] ; s+1,然后存入 rcx(rcx = s+1)
mov QWORD PTR [rbp-8], rcx ; rcx 再压回栈中,供函数使用
movzx edx, BYTE PTR [rdx] ; rdx 所指向的内容即 *t 存入 edx
mov BYTE PTR [rax], dl ; edx 的低 8 位内容存入 rax 所指向的内容即 *s(*s = *t)
movzx eax, BYTE PTR [rax] ; rax 所指向的内容即 *t 存入 eax
test al, al ; 下面判断 eax 即 *t 是否为 0,test 指令是按位与运算
setne al
test al, al
je .L4
jmp .L3
.L4:
nop
pop rbp
ret