C语言中strcat拼接字符串变量与常量的结果差异问题
C语言strcat拼接输出异常原因解析
核心错误根因
你写出的所有代码均触发了C标准定义的未定义行为,出现不同输出完全是编译器内存布局差异导致的巧合,没有必然逻辑:
strcat(dest, src)的强制要求:第一个参数dest必须指向一块可写、剩余空间足够的内存区域,剩余空间至少要能容纳src的所有字符 + 末尾的\0结束符。- 你代码中
char * out = ""的写法,是让out指针指向了只读数据段中的空字符串常量,这块内存存在两个致命问题:- 所属的只读数据段本身不允许修改,强行写入属于非法内存操作
- 仅分配了1字节的存储空间(仅存储了
\0结束符),完全没有多余空间存放拼接的字符串内容
- 未定义行为下程序输出、崩溃、正常运行都属于合理情况,你观测到的不同结果仅仅是不同常量存储顺序下的偶然现象。
不同输出的具体成因
编译器会把程序中用到的所有字符串常量按编译顺序存放在只读数据段的连续区域,你传入strcat的参数形式不同,会改变常量区的存储顺序,进而导致越界写入、读取的内容不同:
- 全部用变量/全部用常量的情况:刚好常量区的存储顺序为
""→HELLO→→WORLD,你越界写入时没有破坏读取逻辑,看起来输出正常,换编译器/编译参数就会发生变化。 - 仅
hello为声明变量的情况:常量区存储的HELLO常量刚好在空字符串后面的连续地址,你越界写入后读取时读到了重叠的常量内容,就出现了HELLOELLOLOELLO的重复输出。 hello和world为声明变量的情况:常量区顺序为""→HELLO→WORLD,越界写入覆盖了部分HELLO常量的内容,读取时就得到了HELLOELLOWORLD的结果。
正确的字符串拼接写法
要避免这类问题,必须保证strcat的第一个参数指向可写的、空间足够的缓冲区:
- 栈上分配固定大小数组:
char out[100] = ""; // 栈上分配100字节可写空间,初始化为空字符串
- 堆上动态分配内存:
char *out = malloc(100); // 分配100字节堆空间 memset(out, 0, 100); // 初始化为空 // 程序结束前记得调用free(out)避免内存泄漏
- 优先使用更安全的
strncat接口,明确指定最大拼接长度,避免缓冲区溢出。
内容的提问来源于stack exchange,提问作者zcaudate
相关产品推荐
相关产品推荐

