请考虑以下代码.
int main(void) {
char * test = "abcdefghijklmnopqrstuvwxyz";
test[5] = 'x';
printf("%s\n", test);
return EXIT_SUCCESS;
}
在我看来,这应该打印abcdexghij.但是,它只是终止而不打印任何东西.
int main(void) {
char * test = "abcdefghijklmnopqrstuvwxyz";
printf("%s\n", test);
return EXIT_SUCCESS;
}
然而,这工作得很好,所以我误解了操纵C字符串或其他东西的概念吗?如果它很重要,我正在运行Mac OS X 10.6,它是我正在编译的32位二进制文件.
Joe*_*Joe 28
使用初始化值定义的字符指针进入只读段.要使它们可修改,您需要在堆上创建它们(例如使用new/malloc)或将它们定义为数组.
不可修改:
char * foo = "abc";
Run Code Online (Sandbox Code Playgroud)
修改:
char foo[] = "abc";
Run Code Online (Sandbox Code Playgroud)
这个答案很好,但还不完全.
char * test = "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
甲文字串是指类型的匿名数组对象char[N]具有静态存储的持续时间(这意味着它存在该程序的整个执行),其中,N是字符串的长度加上一个用于终止'\0'.此对象不是const,但任何修改它的尝试都有未定义的行为.(如果选择,实现可以使字符串文字可写,但大多数现代编译器都不会.)
上面的声明创建了一个类型的匿名对象char[27],并使用该对象的第一个元素的地址进行初始化test.因此,一个赋值就像test[5] = 'x'尝试修改数组,并具有未定义的行为; 通常它会使你的程序崩溃.(初始化使用地址,因为文字是数组类型的表达式,在大多数上下文中隐式转换为指向数组第一个元素的指针.)
请注意,在C++中,字符串文字实际上是const,并且上述声明是非法的.在C或C++中,最好将其声明test为指向const 的指针char:
const char *test = "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
因此,如果您尝试通过修改数组,编译器将发出警告test.
(C字符串文字不是const出于历史原因.在1989 ANSI C标准之前,const关键字不存在.要求它在像你这样的声明中使用会产生更安全的代码,但它需要修改现有代码, ANSI委员会试图避免的事情.你应该假装字符串文字是const,即使它们不是.如果你碰巧使用gcc,该-Wwrite-strings选项将导致编译器将字符串文字视为const- 这使得gcc不符合.)
如果您希望能够修改test引用的字符串,可以像这样定义它:
char test[] = "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
编译器会查看初始化程序以确定test需要的大小.在这种情况下,test将是类型char[27].字符串文字仍然引用匿名的大多数只读数组对象,但其值被复制到test.(用于初始化数组对象的初始值设定项中的字符串文字是数组不会"衰减"到指针的上下文之一;其他的是当它是一元&或或者的操作数时sizeof.)因为没有进一步的引用匿名数组,编译器可能会优化它.
在这种情况下,test它本身是一个包含您指定的26个字符的数组,以及'\0'终结符.该数组的生命周期取决于test声明的位置,这可能或不重要.例如,如果您这样做:
char *func(void) {
char test[] = "abcdefghijklmnopqrstuvwxyz";
return test; /* BAD IDEA */
}
Run Code Online (Sandbox Code Playgroud)
调用者将收到指向不再存在的内容的指针.如果需要引用test定义范围之外的数组,可以将其定义为static,或者可以使用malloc以下命令进行分配:
char *test = malloc(27);
if (test == NULL) {
/* error handling */
}
strcpy(test, "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
所以阵列将继续存在,直到你打电话free().非标准strdup()函数执行此操作(由POSIX定义,但不由ISO C定义).
请注意,test根据您的声明方式,可能是指针或数组.如果你传递test给一个字符串函数,或者传递给任何一个函数char*,这个函数无关紧要,但是sizeof test根据test是指针还是数组,它会表现得非常不同.
该comp.lang.c常见问题是优秀的.第8节涉及字符和字符串,问题8.5指向问题1.32,它解决了您的具体问题.第6节介绍了数组和指针之间经常混淆的关系.