为啥使用字符串初始化没有 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 字符串数组的 Visual Studio C++ 初始化序列
C语言 为啥字符数组倒置输出,输入的最后一个字符没有输出 样例输入 7 ABCDEFG 样例输出 G F E D C B A