这个答案很好,但并不完整。
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 节介绍了数组和指针之间经常令人困惑的关系。