字符串在C中是字符数组,以'\0'结尾。初始化可能涉及静态初始化或动态分配后的赋值。
未初始化的局部变量数组内容是不确定的,可能导致未定义行为,比如访问随机内存,程序崩溃或者安全漏洞。特别是当作为字符串使用时,没有'\0'结尾的话,字符串函数如strcpy、strlen会出问题。
接下来,介绍C语言字符数组初始化的6种方式。
char str1[] = {'H','e','l','l','o','\0'}; // 需手动添加终止符
char str2[6] = "World"; // 自动补零
str1 需手动添加 \0,适合精确控制字符内容;
str2 编译器自动补 \0,数组长度需包含终止符。
栈空间分配,内容可修改。
char str3[] = "ESP32-CAM"; // 数组长度10(含\0)
const char *str4 = "READY"; // 只读数据段
str3 是栈数组,长度自动计算为 10(含 \0),内容可修改;
str4 是常量指针,指向只读数据段,修改内容会触发段错误。
差异比较:str3可修改,str4为常量指针.
char str5[20] = "HTTP/1.1"; // 剩余元素自动初始化为0
char str6[8] = { [0] = 'A', [7] = '\0' }; // C99指定初始化器
str5 初始化后剩余元素自动置零,适合预填充缓冲区;
str6 使用 C99 指定初始化器,灵活设置特定位置的值(如固定末尾为 \0)。
适用场景:协议头预初始化(如TCP报文处理)
char *init_str(int size) {
char *p = malloc(size);
if(p) memset(p, 0, size); // 安全初始化
return p;
}
动态分配内存并初始化为全零,避免脏数据(malloc + memset);
优化建议:直接使用 calloc(size, 1) 更高效。
char *cmds[] = {"AT", "CONNECT", "SEND", NULL}; // 指针数组
char log_buf[3][16] = {{0}}; // 全零初始化二维数组
cmds 是指针数组,适合存储命令行参数(以 NULL 结尾);
log_buf 是二维字符数组,全零初始化保证安全访问。
struct Device {
char id[16];
char *name;
} dev = { .id = "DVC_001", .name = "温度传感器" };
结构体成员分别初始化: 为栈上的字符数组, 指向常量字符串;
注意 指向的内容不可修改。
缓冲区溢出:未校验 snprintf 返回值可能导致截断(如设备 ID 超长)。
未初始化问题:局部数组建议用 char buf[64] = {0}; 强制初始化。
常量修改错误:str4[0] = 'X' 会触发段错误(常量区不可写)。
调试技巧:用 hexdump(str, len) 检查实际内存内容,确认 \0 位置。