关于 strcpy 函数的赋值语句
如何理解while (*s++ = *t++)?
1 2 3 4
| void strcpy(char *s, char *t) { while (*s++ = *t++); }
|
该语句等价于while (*(s++) = *(t++))。
赋值语句的结合方向是自右往左,所以从右往左读,可以将*(s++) = *(t++)拆成两条语句:
1 2
| temp = *(t++); *(s++) = temp;
|
也即代码段 A:
1 2 3 4
| temp = *t; t++; *s = temp; s++;
|
赋值语句实际上是一个表达式,等于赋值运算符右边表达式的结果,比如a = b的结果是b。这里右边表达式是*(t++),结果是*t(先使用,后自增),因此原代码可等价于代码段 B:
1 2 3
| while (*t != '\0'){ *(s++) = *(t++); }
|
代码段 A 和 B 结合在一起:
1 2 3 4 5 6 7
| char temp = *t; while (temp != '\0'){ temp = *t; t++; *s = temp; s++; }
|
需要提醒的是,平时不要写这样的代码,可读性较差。
一些汇编
*s++ = *t++的汇编:
1 2 3 4 5 6 7 8
| 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 的汇编:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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
|