6月1日 14:51

C语言字符串函数有哪些坑?strcpy 和 strncpy 有什么区别?

C 语言字符串就是以 \0 结尾的字符数组,标准库 <string.h> 提供了一组操作函数。面试重点不在背函数签名,而在理解哪些函数安全、哪些有坑、为什么有坑。

追问

strcpy 和 strncpy 有什么区别?哪个更安全?

strcpy 无条件拷贝直到遇到 \0,目标缓冲区不够大就溢出——这是 C 语言最经典的安全漏洞来源。strncpy 限定了最大拷贝长度,但有个坑:如果源字符串比指定长度长,拷贝后不会自动补 \0,目标字符串可能不是合法的 C 字符串。正确用法:

c
strncpy(dest, src, sizeof(dest) - 1); dest[sizeof(dest) - 1] = "\0"; // 手动保底

所以 strncpy 不是"更安全的 strcpy",而是"需要你手动补 \0 的 strcpy"。真正安全的选择是 snprintfsnprintf(dest, sizeof(dest), "%s", src); 自动截断并补 \0

strlen 和 sizeof 有什么区别?

strlen 是运行时函数,从指针位置开始数到 \0 为止,返回字符串的实际长度(不含 \0)。sizeof 是编译期运算符,返回变量或类型占用的字节大小。对数组 char s[] = "hello" 来说,sizeof(s) 是 6(含 \0),strlen(s) 是 5。对指针 char *p = "hello" 来说,sizeof(p) 是 4 或 8(指针本身大小),不是字符串长度。这是面试超高频题。

strtok 为什么不是线程安全的?

strtok 内部用一个静态指针记住上次分割的位置,下次调用传 NULL 就从这里继续。两个线程同时用 strtok,静态指针被互相覆盖,结果就乱了。strtok_r 是可重入版本,由调用者自己维护状态指针:

c
char *saveptr; char *token = strtok_r(str, ",", &saveptr); while (token) { // 处理 token token = strtok_r(NULL, ",", &saveptr); }

strcat 有什么问题?怎么安全拼接字符串?

strcat 从目标字符串末尾开始追加,不检查目标缓冲区剩余空间,溢出风险和 strcpy 一样。安全做法用 snprintf

c
char buf[128]; snprintf(buf, sizeof(buf), "%s%s", prefix, suffix);

或者用 strncat,但要自己算剩余空间:strncat(dest, src, sizeof(dest) - strlen(dest) - 1);

C11 的 strcpy_s 值得用吗?

理论上 strcpy_s 会检查目标缓冲区大小,溢出时返回错误而不是崩溃。但它是 C11 可选附件(Annex K),MSVC 支持但 glibc 不支持,跨平台代码用不了。实际项目中更普遍的做法是用 snprintf 或自己封装安全拷贝函数。

标签:C语言