这个答案很好,但并不完整。
char * test = "abcdefghijklmnopqrstuvwxyz";
字符串字面量是指char[N]
具有静态存储持续时间的匿名数组对象(意味着它在程序的整个执行过程中都存在),其中N
是字符串的长度加上终止符的长度'\0'
。此对象不是const
,但任何修改它的尝试都有未定义的行为。(如果选择,实现可以使字符串文字可写,但大多数现代编译器不这样做。)
上面的声明创建了一个类型为 的匿名对象char[27]
,并使用该对象的第一个元素的地址来初始化test
。因此,类似于test[5] = 'x'
尝试修改数组的赋值,并且具有未定义的行为;通常它会使你的程序崩溃。(初始化使用地址,因为字面量是数组类型的表达式,在大多数上下文中它被隐式转换为指向数组第一个元素的指针。)
请注意,在 C++ 中,字符串文字实际上是const
,上面的声明是非法的。在 C 或 C++ 中,最好声明test
为指向const char
的指针:
const char *test = "abcdefghijklmnopqrstuvwxyz";
因此,如果您尝试通过test
.
(C 字符串文字不是const
出于历史原因。在 1989 年 ANSI C 标准之前,该const
关键字不存在。要求在像您这样的声明中使用它会使代码更安全,但它需要修改现有代码, ANSI 委员会试图避免的事情。您应该假装字符串文字是const
,即使它们不是。如果您碰巧使用 gcc,该-Wwrite-strings
选项将导致编译器将字符串文字视为const
-- 这使得 gcc 不合格.)
如果您希望能够修改test
引用的字符串,可以这样定义:
char test[] = "abcdefghijklmnopqrstuvwxyz";
编译器查看初始化程序以确定需要多大test
。在这种情况下,test
将是类型char[27]
。字符串字面量仍然引用匿名的大部分只读数组对象,但它的值被复制到test
. (用于初始化数组对象的初始化程序中的字符串文字是数组不会“衰减”为指针的上下文之一;其他情况是当它是一元&
或的操作数时sizeof
。)因为没有进一步引用匿名数组,编译器可能会将其优化掉。
在这种情况下,它本身是一个包含您指定的 26 个字符以及终止符test
的数组。'\0'
该数组的生命周期取决于test
声明的位置,这可能很重要,也可能无关紧要。例如,如果您这样做:
char *func(void) {
char test[] = "abcdefghijklmnopqrstuvwxyz";
return test; /* BAD IDEA */
}
调用者将收到一个指向不再存在的东西的指针。如果需要引用定义范围之外的数组test
,可以将其定义为static
,也可以使用 进行分配malloc
:
char *test = malloc(27);
if (test == NULL) {
/* error handling */
}
strcpy(test, "abcdefghijklmnopqrstuvwxyz";
因此数组将继续存在,直到您调用free()
. 非标准strdup()
函数执行此操作(它由 POSIX 定义,但不是由 ISO C 定义)。
请注意,它test
可能是指针或数组,具体取决于您如何声明它。如果你传递test
给一个字符串函数,或者传递给任何接受 a 的函数char*
,那没关系,但是sizeof test
根据test
是指针还是数组,类似的东西会表现得非常不同。
comp.lang.c 常见问题解答非常好。第 8 节涵盖字符和字符串,问题 8.5 指向问题 1.32,该问题解决了您的具体问题。第 6 节介绍了数组和指针之间经常令人困惑的关系。