This answer 不错,但还不够完整。
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 的操作数时。)没有对匿名数组的进一步引用,编译器可能会将其优化掉。
在这种情况下,test 本身是一个包含您指定的 26 个字符以及 '\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 传递给一个字符串函数,或者传递给任何接受char* 的函数,那没关系,但是像sizeof test 这样的东西会根据test 是指针还是数组而表现得非常不同.
comp.lang.c FAQ 非常棒。第 8 节涵盖字符和字符串,问题 8.5 指向问题 1.32,该问题解决了您的具体问题。第 6 节介绍了数组和指针之间经常令人困惑的关系。