Cannot modify C string
考虑下面的代码。
1 2 3 4 5 6 7 | int main(void) { char * test ="abcdefghijklmnopqrstuvwxyz"; test[5] = 'x'; printf("%s ", test); return EXIT_SUCCESS; } |
在我看来,这应该打印abcdexghij。但是,它只是在没有打印任何内容的情况下终止。
1 2 3 4 5 6 | int main(void) { char * test ="abcdefghijklmnopqrstuvwxyz"; printf("%s ", test); return EXIT_SUCCESS; } |
不过,这个方法很好,所以我是否误解了操纵C字符串的概念?如果这很重要,我运行的是MacOSX10.6,它是我正在编译的32位二进制文件。
用初始化值定义的字符指针进入只读段。要使它们可修改,您要么需要在堆上创建它们(例如使用new/malloc),要么将它们定义为数组。
不可修改的:
1 | char * foo ="abc"; |
Modifiable:
1 | char foo[] ="abc"; |
这个答案很好,但不完全。
1 | char * test ="abcdefghijklmnopqrstuvwxyz"; |
字符串文字是指具有静态存储持续时间的
上面的声明创建了一个类型为
注意,在C++中,字符串文字实际上是EDCOX1(3),上面的声明是非法的。在C或C++中,最好声明EDOCX1×5作为指向const EDCOX1的指针:9表示:
1 | const char *test ="abcdefghijklmnopqrstuvwxyz"; |
因此,如果您试图通过
(由于历史原因,C字符串文字不是
如果要修改
1 | char test[] ="abcdefghijklmnopqrstuvwxyz"; |
编译器查看初始值设定项以确定
在这种情况下,
1 2 3 4 | char *func(void) { char test[] ="abcdefghijklmnopqrstuvwxyz"; return test; /* BAD IDEA */ } |
调用方将收到指向不再存在的内容的指针。如果需要引用定义
1 2 3 4 5 |
所以数组将继续存在,直到您调用
请注意,
comp.lang.c常见问题解答非常好。第8节包括字符和字符串,问题8.5指向问题1.32,该问题解决了您的特定问题。第6节介绍了数组和指针之间经常混淆的关系。
字符串文本可能不可修改;最好假定它们不可修改。有关详细信息,请参阅此处。
您应该养成将变量类型与初始化器类型匹配的习惯。在这种情况下:
1 | const char* test ="abcdefghijklmnopqrstuvwxyz"; |
这样您将得到一个编译器错误而不是运行时错误。将编译器警告级别提高到最大值也有助于避免此类陷阱。为什么这不是C中的一个错误可能是历史性的;早期的编译器允许它,而不允许它可能在语言标准化时破坏了太多的现有代码。但是现在操作系统不允许这样做,所以这是学术性的。
做:
1 2 | char * bar = strdup(foo); bar[5] = 'x'; |
是的,您应该测试