【问题标题】:String literals vs const char* in CC 中的字符串文字与 const char*
【发布时间】:2010-07-21 20:12:40
【问题描述】:

为什么 ANSI C 编译器不标记在相应参数没有 const 限定符的函数调用中使用字符串字面量参数?例如,以下代码可能会通过尝试写入只读内存来生成异常。

void somefunc(char buffer[10]);

void somefunc(char buffer[10]) {
    int i;

    for (i = 0;   i < 10;   i++)
       buffer[i] = 0;
}

int main(int argc, char **argv) {

    somefunc("Literal");
    return 0;
}

这种情况可以在编译时确定,但 VS2010 和 gcc 似乎没有这样做。使用 const char* 参数调用 somefunc 将生成编译器警告。

【问题讨论】:

  • 好问题 - gcc 也没有捕捉到这一点,即使是 -Wextra
  • 声明一个函数,然后在下一行定义它的意义何在? :)
  • Hans:我已经修改了问题以指定 ANSI C。无论如何,我并不是建议发出编译器错误。 3 级或 4 级警告只会突出潜在的危险情况。
  • 附注:main 的参数是倒置的,正确的签名是int main(int argc, char *argv[])
  • 只是为了澄清-我的问题不是“为什么不将字符串文字视为 const char*?”但是“为什么我们在使用字符串文字参数调用 somefunc() 时不会收到编译器警告?”正如 lunaryorn 指出的那样,函数签名为编译器提供了足够的信息来发出此警告。

标签: c


【解决方案1】:

这是 K&R 的遗产。修复它会破坏一百万个程序。

【讨论】:

    【解决方案2】:

    gcc:使用标志-Wwrite-strings

    PS。 gcc 手册解释了为什么这不是 -Wall 的一部分。无论如何,与往常一样,您应该找到适合您的特定需求和编码风格的 -W 标志组合。例如,在最近的一个项目中,我使用了这样的东西:-Werror -Wall -Wextra -Wformat=2 -Winit-self -Wswitch-enum -Wstrict-aliasing=2 -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wdisabled-optimization -Wunused-macros -Wno-unused

    【讨论】:

      【解决方案3】:

      汉斯·帕桑特所说的。 const 在 1989 年被添加为 ANSI 标准的一部分,因此之前的任何内容都没有 const。

      【讨论】:

      • @Georg:我的意思是 const 关键字是在 ANSI C 中添加的,所以用 const 来改造字符串文字已经太迟了。
      【解决方案4】:

      字符串文字在 C 中不是 const;在 C++ 中它们是。

      编辑:为了消除对我评论的任何混淆,我指的是类型,而不是实际更改它们的能力。

      【讨论】:

      • @Paul,他是对的。 C99 §6.4.5/5:“对于字符串文字,数组元素的类型为char”未定义修改字符串文字,但元素类型为char,而不是const char
      • @Matthew:感谢您的澄清-我将“const”解释为“只读”(当然,字符串文字通常在 C 或 C++ 中)但我明白你的意思现在字符串文字的实际 type
      【解决方案5】:

      如果使用-Wwrite-string,GNU 编译器(以及英特尔 C 编译器 iirc)将发出警告:

      $ gcc -Wall -Wwrite-strings -o foo /tmp/foo.c
      /tmp/foo.c: In function 'main':
      /tmp/foo.c:12: warning: passing argument 1 of 'somefunc' discards qualifiers from pointer target type
      /tmp/foo.c:3: note: expected 'char *' but argument is of type 'const char *'
      

      关于VS2010,我帮不了你。

      【讨论】:

      • 酷 - 我想知道为什么 -Wwrite-strings 不包含在 -Wall 甚至 -Wextra 中?
      猜你喜欢
      • 2020-01-03
      • 1970-01-01
      • 2011-05-20
      • 2018-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2010-09-21
      相关资源
      最近更新 更多