您应该做的第一件事是阅读comp.lang.c FAQ的第 6 部分。
字符串字面"hello"
量是一个类型的表达式char[6]
(“hello”为 5 个字符,结尾为 1 个字符'\0'
)。它指的是一个具有静态存储持续时间的匿名数组对象,在程序启动时初始化为包含这 6 个字符值。
在大多数情况下,数组类型的表达式被隐式转换为指向数组第一个元素的指针;例外情况是:
- 当它是
sizeof
(的参数时,sizeof "hello"
产生 6,而不是指针的大小);
- 当它是
_Alignof
(C11 中的一个新特性)的论点时;
- 当它是一元的参数时
&
(&arr
产生整个数组的地址,而不是其第一个元素的地址;相同的内存位置,不同的类型);和
- 当它是用于初始化数组对象的初始化程序中的字符串文字时(
char s[6] = "hello";
复制整个数组,而不仅仅是指针)。
这些例外都不适用于您的代码:
char *ptr;
ptr = "hello";
所以表达式"hello"
被转换为(“衰减”到)指向'h'
我上面提到的那个匿名数组对象的第一个元素()的指针。
因此*ptr == 'h'
,您可以ptr
通过记忆前进以访问其他字符:'e'
、'l'
、'l'
、'o'
和'\0'
。printf()
当你给它一个"%s"
格式时,这就是它的作用。
与字符串文字相关联的匿名数组对象是只读的,但不是const
. 这意味着任何修改该数组或其任何元素的尝试都具有未定义的行为(因为标准明确说明了这一点)——但编译器不一定会警告您。(C++ 生成字符串文字const
;在 C 中做同样的事情会破坏在添加到语言中之前编写的现有代码const
。)所以不,你不能修改"hello"
- 或者至少你不应该尝试的元素。为了让编译器在您尝试时发出警告,您应该将指针声明为const
:
const char *ptr; /* pointer to const char, not const pointer to char */
ptr = "hello";
(gcc 有一个选项 ,-Wwrite-strings
导致它将字符串文字视为const
。这将导致它警告一些就标准而言是合法的 C 代码,但此类代码可能应该修改为使用const
。)