为什么 C 编译器不警告与文字字符串不兼容的类型?

Why don't C compilers warn about incompatible types with literal strings?

以下程序由于未定义的行为(试图修改字符串文字)而引发系统分段错误:

int main() {
  char *s = "immutable";
  s[0] = 'a';
  return 0;
}

不过,似乎绝对没有办法让 GCC/Clang 发出哪怕是最轻微的警告(-Wall -Wextra -pedantic -std=c11 不要做任何事情)。

特别是初学者,遇到这种情况,多多告知。即使对于非初学者,在一些不太明显的情况下也可能有所帮助:

void f(char *s) {
  s[0] = '0';
}

int main() {
  char *s = "immutable";
  f("literal"); // oops
  f(s); // oops
  return 0;
}

此外,这将有助于在 C 编程中加强某些 const 文化。

为什么故意忽略这种情况?该标准是否主动禁止在这种情况下发出诊断信息,或者主要是为了向后兼容(现在尝试强制执行它们会产生太多警告)?

有一个选项:-Wwrite-strings。它通过将字符串文字的类型从 char[N] 更改为 const char[N] 来工作。此更改与标准 C 不兼容,将导致拒绝有效代码,并在极少数情况下静默接受无效代码。默认情况下未启用。

不幸的是,由于字符串文字在 C 中的定义方式,在不更改语言的情况下提供良好的警告非常困难。

TL;DR C 编译器不会发出警告,因为它们 "see" 没有问题出现。根据定义,C 字符串文字是空终止的 char 数组。只是说,

[...] If the program attempts to modify such an array, the behavior is undefined.

因此,在编译过程中,编译器不知道 char 数组应该表现为 字符串文字 字符串。仅禁止修改.

相关阅读:任何感兴趣的人,请参阅Why are C string literals read-only?

也就是说,我不太确定这是否是一个 好的 选项,但是 gcc-Wwrite-strings 选项。

引用 online manual,

-Wwrite-strings

When compiling C, give string constants the type const char[length] so that copying the address of one into a non-const char * pointer produces a warning. These warnings help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it is just a nuisance. This is why we did not make -Wall request these warnings.

因此,它使用 后门 方式产生警告。

根据定义,C 字符串文字(即字符串文字)是 char 具有空终止符的数组。该标准并未强制要求它们必须 const 合格。

参考:C11,章节

In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence. [....]

使用上述选项使 字符串文字 const 合格,因此使用字符串文字作为分配给非常量类型指针的 RHS 会触发警告。

这是参考 C11 章节 §6.7.3

完成的

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. [...]

因此,此处编译器会针对将 const 限定类型分配给非 const 限定类型产生警告。

与为什么使用 -Wall -Wextra -pedantic -std=c11 不会产生此警告有关,是再次引用引号

[...] These warnings help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it is just a nuisance. This is why we did not make -Wall request these warnings.