在 C 语言中,将字符串赋值为空(即空字符串)有几种常见的方法,核心思想是:让字符串的第一个字符是空字符 \0,并且确保字符串有足够的空间来容纳这个空字符。

(图片来源网络,侵删)
下面我将详细解释几种方法,并指出它们的优缺点和适用场景。
使用空字符串字面量(最常用、最推荐)
这是最直接、最清晰的方法,在 C 语言中,空字符串 本身就代表一个只包含空字符 \0 的字符串。
代码示例:
#include <stdio.h>
#include <string.h> // 用于 strlen() 函数
int main() {
// 1. 定义时直接初始化为空字符串
// char str[10] = ""; // 推荐:同时指定数组大小,更安全
// char str[] = ""; // 也可以,编译器会自动分配空间(大小为1,只够存\0)
// 2. 先定义,再赋值
char str[50];
str[0] = '\0'; // 手动设置第一个字符为空字符,其余字符保持未定义状态
// 或者直接使用 strcpy
strcpy(str, ""); // 将空字符串拷贝到 str 中
printf("str 的内容: \"%s\"\n", str);
printf("str 的长度: %zu\n", strlen(str)); // strlen 返回 0
printf("str 的地址: %p\n", (void*)str);
return 0;
}
优点:

(图片来源网络,侵删)
- 简洁明了: 直观地表达了“空字符串”的意图。
- 高效:编译器会对此进行优化,直接在内存中放置一个
\0。 - 安全:当与固定大小的字符数组一起使用时,可以防止缓冲区溢出。
注意:
- 如果你使用
char str[] = "";,编译器会分配一个大小为 1 的数组,因为它只需要存储一个\0。 - 如果你使用
char *str = "";,str将成为一个指向只读内存区域的指针(通常是程序的只读数据段),你不能修改这个指针指向的内容,但可以修改指针本身让它指向别处,对于需要修改内容的字符串,强烈建议使用字符数组。
使用 strcpy() 函数
strcpy() 函数用于将源字符串拷贝到目标字符数组中,当源字符串是空字符串 时,它实际上只拷贝了一个 \0 到目标位置。
代码示例:
#include <stdio.h>
#include <string.h>
int main() {
char destination[100]; // 确保目标缓冲区足够大
// 将空字符串拷贝到 destination
strcpy(destination, "");
printf("destination 的内容: \"%s\"\n", destination);
printf("destination 的长度: %zu\n", strlen(destination)); // 0
return 0;
}
优点:

(图片来源网络,侵删)
- 代码意图清晰,
strcpy明确表示这是一个拷贝操作。 - 是处理字符串拷贝的标准函数。
缺点:
- 需要包含
<string.h>。 - 如果目标缓冲区不够大,会导致缓冲区溢出,这是严重的安全隐患。使用
strcpy必须确保目标空间足够大。
手动设置第一个字符为 \0
这是最底层的方法,字符串在 C 中就是以 \0 结尾的字符数组,只要数组的第一个字符是 \0,无论后面是什么,strlen 和 printf("%s", ...) 都会认为这是一个空字符串。
代码示例:
#include <stdio.h>
#include <string.h>
int main() {
char my_string[20];
// 手动将第一个字符设置为空字符
my_string[0] = '\0';
// my_string 的其余 19 个字节是未初始化的垃圾值
// 但对于字符串函数来说,它已经是空字符串了
printf("my_string 的内容: \"%s\"\n", my_string);
printf("my_string 的长度: %zu\n", strlen(my_string)); // 0
// 你可以安全地在其后追加内容
strcat(my_string, "Hello World!");
printf("追加后的内容: \"%s\"\n", my_string);
return 0;
}
优点:
- 不依赖任何库函数,只使用 C 语言的基本特性。
- 对于性能要求极高的场景,可能比调用
strcpy稍快(但现代编译器通常会优化掉这种差异)。
缺点:
- 可读性稍差:不如 或
strcpy直观。 - 不安全:只设置了第一个字符,如果后续代码依赖于整个数组的初始化状态,可能会出现问题,它只保证了字符串的正确性,没有保证整个数组的“干净”。
使用 memset() 函数
memset() 函数用于将一块内存区域的所有字节都设置为指定的值,如果你想将整个字符串缓冲区清零,这是一个很好的选择。
代码示例:
#include <stdio.h>
#include <string.h>
int main() {
char buffer[50];
// 将 buffer 的前 50 个字节全部设置为 0 (即 '\0')
memset(buffer, 0, sizeof(buffer));
// 因为第一个字节是 '\0',所以它是一个空字符串
printf("buffer 的内容: \"%s\"\n", buffer);
printf("buffer 的长度: %zu\n", strlen(buffer)); // 0
// 整个 buffer 现在都是 0,非常干净安全
// 你可以安全地使用 sprintf, strcat 等函数
sprintf(buffer, "Value: %d", 123);
printf("buffer 的新内容: \"%s\"\n", buffer);
return 0;
}
优点:
- 非常安全:将整个缓冲区清零,不仅创建了空字符串,还清除了所有可能存在的“垃圾数据”,有效防止了信息泄露和潜在的逻辑错误。
- 通用性强:可以用于清零任何类型的数据块,而不仅仅是字符串。
缺点:
- 开销稍大:它需要遍历整个缓冲区来设置每个字节,而方法一只设置一个字节,但对于大多数应用来说,这种差异可以忽略不计。
- 需要包含
<string.h>。
总结与最佳实践
| 方法 | 示例 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 空字符串字面量 | char str[10] = ""; |
最简洁、最直观、最安全 | 无明显缺点 | 初始化时首选,强烈推荐。 |
strcpy() 函数 |
strcpy(str, ""); |
意图清晰,是标准字符串操作 | 需要包含头文件,有缓冲区溢出风险 | 在已有代码库或需要明确表达“拷贝”意图时使用。务必保证目标空间足够。 |
手动设置 \0 |
str[0] = '\0'; |
不依赖库,可能高效 | 可读性差,不安全(未初始化其余部分) | 对性能有极致要求的底层代码,或者当你只想快速清空字符串内容而不关心整个数组时。 |
memset() 函数 |
memset(str, 0, sizeof(str)); |
最安全,清零整个缓冲区 | 开销稍大,需要包含头文件 | 需要清零整个缓冲区时的最佳选择,例如在函数开始时清理一个局部缓冲区,防止信息泄露。 |
核心建议:
- 定义并初始化时:使用
char my_str[SIZE] = "";,这是最安全、最清晰的方式。 - 清空一个已有的、足够大的字符串缓冲区:使用
memset(buffer, 0, sizeof(buffer));,这是最彻底、最安全的方式。 - 在代码逻辑中需要将一个字符串变量清空:使用
my_str[0] = '\0';是一个高效且常见的做法。
绝对要避免的错误:
char *str = NULL;:这表示指针str不指向任何有效内存,它不是一个空字符串,尝试对str使用任何字符串函数(如strlen,printf)都会导致未定义行为,通常是程序崩溃(段错误)。char str[10];// 未初始化:str的内容是随机的,printf("%s", str)会打印出内存中的垃圾数据,直到遇到第一个\0,这可能导致信息泄露或程序崩溃。
