strcat 函数简介
我们回顾一下标准库中 strcat 函数的行为:

(图片来源网络,侵删)
#include <string.h> char *strcat(char *dest, const char *src);
功能:
将 src (source) 指向的字符串追加到 dest (destination) 指向的字符串的末尾。
关键点:
- 目标字符串 (
dest) 必须有足够的空间来容纳dest原有的内容 +src的内容 + 一个额外的\0(空字符),如果空间不足,会导致缓冲区溢出,这是非常危险的。 - 追加操作会覆盖
dest原有字符串末尾的\0。 - 函数返回
dest指针。 src指向的字符串是const,表示strcat函数不会修改源字符串。
实现思路
要手动实现 strcat,我们可以分三步走:
- 找到目标字符串的末尾:遍历
dest字符串,直到找到其结尾的空字符\0,指针就指向了可以开始追加新字符的位置。 - 复制源字符串:从
src字符串的第一个字符开始,将其逐个字符复制到dest的末尾位置,直到src也遇到\0为止。 - 添加终止符:将
\0追加到新拼接好的字符串末尾。
C语言代码实现
下面是一个完整的、带有注释的实现代码。

(图片来源网络,侵删)
#include <stdio.h>
/**
* @brief 将源字符串 src 追加到目标字符串 dest 的末尾
*
* @param dest 目标字符串,必须有足够的空间
* @param src 源字符串
* @return char* 返回目标字符串 dest 的指针
*/
char *my_strcat(char *dest, const char *src) {
char *ptr = dest; // 保存 dest 的起始地址,用于最后返回
// 1. 移动指针到 dest 字符串的末尾
// 循环直到找到 dest 字符串的结束符 '\0'
while (*dest != '\0') {
dest++;
}
// 2. 将 src 字符串的内容复制到 dest 的末尾
// 循环直到找到 src 字符串的结束符 '\0'
// 循环结束后,'\0' 也会被复制过去
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
// 3. 确保新字符串以 '\0' (虽然上面的循环已经完成了这一步,但显式写出更清晰)
*dest = '\0';
// 4. 返回目标字符串的起始地址
return ptr;
}
// --- 测试代码 ---
int main() {
// char 数组必须足够大,以容纳结果
char str1[50] = "Hello, "; // 初始化,注意留出足够空间
char str2[] = "world!";
printf("strcat 前:\n");
printf("str1: \"%s\"\n", str1);
printf("str2: \"%s\"\n", str2);
// 调用我们自己的 my_strcat 函数
my_strcat(str1, str2);
printf("\nstrcat 后:\n");
printf("str1: \"%s\"\n", str1);
// 测试链式追加
char str3[100] = "This is a test";
my_strcat(str3, " of the ");
my_strcat(str3, "emergency broadcast system.");
printf("\n链式追加结果:\n");
printf("str3: \"%s\"\n", str3);
return 0;
}
代码解析:
-
*`char my_strcat(char dest, const char src)`**
- 函数签名与标准库
strcat一致。src被声明为const char *,这是一个好习惯,表明我们承诺不会修改src的内容。
- 函数签名与标准库
-
*`char ptr = dest;`**
- 我们创建一个临时指针
ptr来保存dest的原始地址,因为在接下来的操作中,dest指针会不断移动,最终指向字符串的末尾,我们需要返回的是字符串的起始地址,ptr派上了用场。
- 我们创建一个临时指针
-
*`while (dest != '\0') { dest++; }`**
- 这是第一步。
*dest解引用dest指针,获取它当前指向的字符,只要这个字符不是\0,我们就让dest指针向前移动一个位置,当循环结束时,dest指针恰好指向了dest原字符串末尾的\0的位置,也就是新内容应该开始的位置。
- 这是第一步。
-
*`while (src != '\0') { dest = src; dest++; src++; }`**
(图片来源网络,侵删)- 这是第二步。
dest和src都指向各自字符串的有效内容,我们进入一个循环,将src指向的字符赋值给dest指向的位置,然后两个指针都向前移动,这个过程会一直持续,直到src指向\0,在最后一次赋值时,*dest = *src实际上就是*dest = '\0',这完美地完成了为新字符串添加终止符的工作。
- 这是第二步。
-
*`dest = '\0';`**
- 虽然上面的循环已经将
src的\0复制过来了,但显式地再写一遍可以增加代码的可读性和健壮性,明确表示我们在这里确保字符串的正确终止。
- 虽然上面的循环已经将
-
return ptr;- 返回我们一开始保存的
dest的起始地址。
- 返回我们一开始保存的
安全版本实现:strncat
标准库还提供了一个更安全的版本 strncat,它允许你指定最多追加多少个字符,从而防止缓冲区溢出。
char *strncat(char *dest, const char *src, size_t n);
我们可以基于同样的思路实现 my_strncat。
/**
* @brief 将源字符串 src 的前 n 个字符追加到目标字符串 dest 的末尾
*
* @param dest 目标字符串,必须有足够的空间
* @param src 源字符串
* @param n 要追加的最大字符数
* @return char* 返回目标字符串 dest 的指针
*/
char *my_strncat(char *dest, const char *src, size_t n) {
char *ptr = dest;
// 1. 移动指针到 dest 字符串的末尾
while (*dest != '\0') {
dest++;
}
// 2. 复制 src 的前 n 个字符,或者直到遇到 src 的 '\0'
while (n > 0 && *src != '\0') {
*dest = *src;
dest++;
src++;
n--; // 每复制一个字符,n 就减 1
}
// 3. 确保新字符串以 '\0'
*dest = '\0';
return ptr;
}
// --- 测试 my_strncat ---
int main_strncat_test() {
char str1[20] = "Hello"; // 目标空间有限
char str2[] = " world, this is a very long string!";
printf("\n--- strncat 测试 ---\n");
printf("strcat 前: \"%s\"\n", str1);
printf("str2: \"%s\"\n", str2);
// 只追加 str2 的前 7 个字符(包括空格)
my_strncat(str1, str2, 7);
printf("strncat 后: \"%s\"\n", str1); // 输出 "Hello world"
return 0;
}
my_strncat 的核心区别在于第二个 while 循环的条件:while (n > 0 && *src != '\0'),它会同时检查是否还有可追加的字符数 (n > 0) 以及源字符串是否已经结束 (*src != '\0'),这样就确保了不会追加超过 n 个字符,从而保证了安全性。
实现 strcat 的核心在于熟练运用指针来遍历和操作字符数组,并始终牢记字符串以 \0 结尾这一关键特性,理解了 strcat 的实现,对于掌握C语言中的指针和字符串操作非常有帮助,也必须时刻警惕缓冲区溢出的风险,在实际编程中优先考虑使用更安全的 strncat 或其他有边界检查的字符串处理函数。
