为啥使用字符串初始化没有 const 的数组时 gcc 不给出警告?

Posted

技术标签:

【中文标题】为啥使用字符串初始化没有 const 的数组时 gcc 不给出警告?【英文标题】:Why gcc does not give a warning when you initialize an array without const with strings?为什么使用字符串初始化没有 const 的数组时 gcc 不给出警告? 【发布时间】:2016-10-09 22:54:40 【问题描述】:
#include <stdio.h>

void print(char *strings[]) 
  while (*strings) printf("%s\n", *strings++);


int main(int argc, char *argv[]) 

  char *array[] = "Hello", "World", NULL; // No warning?
  const char *constArray[] = "Hello", "World", NULL;

  print(constArray); // Warning!

  //constArray[0][0] = '!'; Compile time error
  array[0][0] = '!'; // Run time error

  return 0;

我期待在char *array[] = "Hello", "World", NULL; 中收到警告,因为这些字符串的字符是只读的,但编译器并没有对此发出警告。所以基本上编译器让我在没有警告的情况下让我将const char“转换”为char

当将const char 传递给在print(constArray); 中接收char 的函数时,换句话说,将const char“转换”为char,编译器确实会给我一个警告。我希望编译器在这两种情况下都给我一个警告,或者都不给我一个警告,但不是在一种情况下,也不是在另一种情况下。

我认为这个警告对于防止出现array[0][0] = '!'; 中的错误很重要。那么为什么我在第一次初始化时没有收到警告呢?

【问题讨论】:

即使字符串是只读的,指针也不是。可以在没有任何警告的情况下更改它们,这没关系。 @tofro,是的,但这不是重点。 const char * 类型的值不能分配给char * 类型的左值——它违反了标准的第 6.5.16/1 段。这里的问题部分是“只读”是对字符串文字的糟糕描述,并且无论如何它都不等同于const。该标准并没有说字符串文字是只读的;它说试图修改它们的值会产生未定义的行为。这是一个很好但很重要的区别。 【参考方案1】:

那么为什么我在第一次初始化时没有收到警告?

因为字符串文字的类型是char 的数组,而不是const char 的数组,尽管修改此类数组的元素会产生未定义的行为。这源于 C 语言的最初几天,当时没有 const。我确信它在现代 C 中的持久性是围绕着如果类型改变会出现的不兼容的大小和范围。

但是,对于个别程序,GCC 可以为您提供帮助。如果你打开它的-Wwrite-strings 选项,那么它确实会给出字符串文字类型const char [length],结果是像你这样的构造会引发警告。

【讨论】:

【参考方案2】:

编译器不会警告您,因为 C 标准不要求字符串字面量为 const。

Why doesn't the compiler detect and produce errors when attempting to modify char * string literals?

Why do compilers allow string literals not to be const?

【讨论】:

以上是关于为啥使用字符串初始化没有 const 的数组时 gcc 不给出警告?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我可以从 char * const 值创建 char * 向量?

为啥允许我在 C 中使用 const 限定变量作为数组大小?

为啥 const 限定变量被接受为 gcc 上的初始化程序?

为啥文字不是 const (字符串除外)?

如何更改静态链接库中 const 字符串数组的 Visual Studio C++ 初始化序列

C语言 为啥字符数组倒置输出,输入的最后一个字符没有输出 样例输入 7 ABCDEFG 样例输出 G F E D C B A