strcat 的执行顺序可以概括为 “先复制,后追加”。

它首先会找到目标字符串的末尾('\0'),然后从该位置开始,将源字符串的内容(包括其结尾的 '\0')依次复制到目标字符串的末尾。
详细执行步骤
假设我们有以下代码:
#include <stdio.h>
#include <string.h>
int main() {
char dest[20] = "Hello, "; // 目标字符串
char src[] = "World!"; // 源字符串
printf("调用 strcat 前:\n");
printf("dest = \"%s\"\n", dest);
printf("src = \"%s\"\n", src);
// 调用 strcat 函数
strcat(dest, src);
printf("\n调用 strcat 后:\n");
printf("dest = \"%s\"\n", dest);
return 0;
}
strcat(dest, src) 的具体执行顺序如下:
步骤 1:定位目标字符串的末尾
函数首先会从 dest 字符串的第一个字符开始,向后查找,直到找到字符串的结束标记 '\0'。

dest的初始内容是:'H', 'e', 'l', 'l', 'o', ',', ' ', '\0'- 函数找到
'\0'的位置,在这个例子中,'\0'位于索引 7(如果从0开始计数)。 - 这个位置就是新的写入起点。
步骤 2:从源字符串读取并复制到目标字符串
函数开始从 src 字符串的第一个字符读取,并将其逐个复制到 dest 字符串从 '\0' 位置开始的地方。
- 读取
src的第一个字符'W',将其写入dest的索引 7 位置。dest变为:'H', 'e', 'l', 'l', 'o', ',', ' ', 'W'
- 读取
src的第二个字符'o',将其写入dest的索引 8 位置。dest变为:'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o'
- ...这个过程持续进行...
- 读取
src的最后一个字符 ,将其写入dest的某个位置(比如索引 11)。dest变为:'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!'
- 读取
src的结束标记'\0',将其写入dest的下一个位置(索引 12)。dest最终变为:'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\0'
步骤 3:函数返回
strcat 函数执行完毕,并返回 dest 字符串的起始地址(即指向 dest[0] 的指针),虽然我们可以接收这个返回值,但在大多数情况下,我们都会忽略它,因为我们知道操作是直接在 dest 上进行的。
dest 的内容就变成了 "Hello, World!"。
图示说明
让我们用图来更直观地展示这个过程。

初始状态:
内存地址: 100 101 102 103 104 105 106 107 108 ...
dest: 'H' 'e' 'l' 'l' 'o' ',' ' ' '\0' ? ...
src: 'W' 'o' 'r' 'l' 'd' '!' '\0'
步骤 1: 定位 dest 的末尾 ('\0')
函数发现 dest 的 '\0' 在地址 106。
步骤 2: 开始追加 src 的内容
内存地址: 100 101 102 103 104 105 106 107 108 109 110 111 112 ...
dest: 'H' 'e' 'l' 'l' 'o' ',' ' ' 'W' 'o' 'r' 'l' 'd' '!' '\0'
src: 'W' 'o' 'r' 'l' 'd' '!' '\0'
src的'W'(地址 100) -> 复制到dest的地址 107src的'o'(地址 101) -> 复制到dest的地址 108src的 (地址 105) -> 复制到dest的地址 111src的'\0'(地址 106) -> 复制到dest的地址 112
最终状态:
dest 指向一个完整的字符串 "Hello, World!",而 src 保持不变。
重要注意事项(陷阱)
-
目标缓冲区必须足够大 这是最重要的一点。
strcat不会检查目标缓冲区dest是否有足够的空间来容纳源字符串src。dest的大小不够,就会发生缓冲区溢出,这会覆盖dest之后的内存数据,导致程序崩溃、数据损坏或严重的安全漏洞(如被黑客利用)。错误示例:
char dest[6] = "Hello"; // 只有6字节空间,最后一个给 '\0' char src[] = "World!"; // 需要6字节空间(5个字符 + '\0') strcat(dest, src); // 崩溃!dest 只有6字节,无法容纳 "Hello" + "World!"
-
目标字符串必须以
'\0'dest没有正确的'\0'strcat函数将无法找到字符串的末尾,它会一直向后读取内存,直到偶然遇到一个值为 0 的字节,这同样会导致越界访问和未定义行为。 -
源字符串不会被修改
strcat是一个只读操作,它只读取src的内容,不会改变src的任何内容。
更安全的替代方案
为了防止缓冲区溢出,C 标准库提供了更安全的版本 strncat。
strncat(dest, src, n): 它最多从src中复制n个字符到dest的末尾。- 关键点:
strncat保证目标字符串dest总是以'\0'即使src的长度小于n,它也会在复制完src后添加'\0';src的长度大于或等于n,它只会复制n个字符,然后强制在末尾添加一个'\0'。
使用 strncat 的安全示例:
#include <stdio.h>
#include <string.h>
int main() {
char dest[20] = "Hello, ";
char src[] = "World!";
// 安全地追加,最多追加 sizeof(dest) - 1 - strlen(dest) 个字符
// sizeof(dest) - 1 是为了留出 '\0' 的位置
// strlen(dest) 是 "Hello, " 的长度
// 所以最多可以追加 20 - 1 - 7 = 12 个字符,足以容纳 "World!"
strncat(dest, src, sizeof(dest) - strlen(dest) - 1);
printf("dest = \"%s\"\n", dest); // 输出: dest = "Hello, World!"
return 0;
}
| 特性 | 描述 |
|---|---|
| 执行顺序 | 先找 dest 的末尾 '\0',然后从该位置开始,将 src 的内容(包括 '\0')复制过去。 |
| 关键操作 | 复制,它不是简单地拼接两个字符串,而是将一个字符串的内容复制到另一个字符串的末尾。 |
| 安全性 | 不安全,容易导致缓冲区溢出。 |
| 使用前提 | dest 必须有足够大的空间,并且必须以 '\0'
|
| 推荐替代 | 使用 strncat 并正确计算要复制的最大字符数,以防止缓冲区溢出。 |
