字符数组与字符指针:为何某场景可行另一场景失效?
字符指针指向字符串常量时调用strcpy失效的原因
三段代码对比
第一段代码(正常运行)
#include <stdio.h> int main(void) { char* f = "test"; printf("%s", f);//prints "test" }
这段代码能正常打印,是因为字符指针只是读取字符串常量的内容,没有修改操作,完全合法。
第二段代码(正常运行)
#include <stdio.h> void strcpy(char* dst, char* src) { int i = 0; do { *(dst + i) = *(src + i); } while (*(src + (i++))); } int main(void) { char first[] = "test2"; char second[] = "test3"; strcpy(second, first); printf("%s", second); //prints "test2" }
此处second是栈上分配的字符数组,内存属于可修改区域,strcpy的写入操作合法,因此能正常覆盖内容并打印结果。
第三段代码(出现问题)
#include <stdio.h> void strcpy(char* dst, char* src) { int i = 0; do { *(dst + i) = *(src + i); } while (*(src + (i++))); } int main(void) { char first[] = "test4"; char *second = "test5"; //ONLY THIS LINE IS CHANGED strcpy(second, first); printf("%s", second); //PRINTS NOTHING }
仅修改一行代码后程序就无法正常输出,核心原因如下:
问题本质
char *second = "test5"中,"test5"是字符串常量,它被存储在程序的只读数据段(.rodata)中,操作系统会将这块内存标记为只读属性,禁止任何写入操作。- 你的
strcpy函数试图往second指向的只读内存地址写入数据,这触发了未定义行为。未定义行为的表现没有固定标准:可能直接崩溃,可能输出乱码,也可能像你遇到的那样无输出,甚至在某些环境下看似正常,但这种操作绝对违反了C语言的内存规则。
关键区别
char second[] = "test3"和char *second = "test5"是完全不同的两种内存分配方式:
- 前者是在栈上创建字符数组,并用字符串常量初始化数组内容,数组本身的内存是可修改的;
- 后者是让指针直接指向只读数据段中的字符串常量,指针指向的内存不可修改。
额外提示:按照C标准,字符串常量的类型是const char[],虽然允许用char*指向它,但这是历史兼容写法。为了避免误修改,建议用const char*来声明指向字符串常量的指针,编译器会在你试图修改时直接报错,提前发现问题。
内容的提问来源于stack exchange,提问作者user394334
相关产品推荐
相关产品推荐

