在第一种情况下,您面临未定义的行为通过尝试修改字符串字面量。分段错误是常见的错误之一副作用 of UB.
在你的代码中,
char *s = "hello";
essentially puts the starting address of the string literal "hello"
into s
. Now, is you want to modify the content of *s
(or *(s+n)
, provided n
does not go out of bounds), it will actually try to modify that string literal. As usually, the string literals are stored in the read-only memory, they are usually not allowed to be modified. Quoting from C11
, chapter §6.4.5, String literals, (emphasis mine)
如果这些数组的元素具有适当的值,则未指定这些数组是否不同。如果程序尝试修改这样的数组,则行为是未定义的。
然而,在你的第二种情况下,你正在做
char *s = argv[1];
这是把值argv[1]
into s
. Now, s
指向string包含于argv[1]
。这里,内容为argv[1]
(or, argv[n]
,一般来说)不是只读的,它可以修改。所以,使用*s
(or *(s+n)
, 假如n
不越界),可以修改内容。
这个案例是定义的行为,因为根据 §5.1.2.2.2,程序启动
参数argc
and argv
和指向的字符串argv
数组应可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值。
所以,第二种情况是special使用时的情况argv[n]
,这是由C标准规则决定的,可修改的。