【问题标题】:GCC - shouldn't a warning be issued when assigning an int to a char?GCC - 将 int 分配给 char 时不应该发出警告吗?
【发布时间】:2010-12-16 08:38:28
【问题描述】:

我最近在我的笔记本电脑上设置了一个 MinGW + MSYS 环境,以检查 Netbeans C/C++ 支持情况如何。一切似乎都运行良好,但是,在我的测试过程中,我注意到 GCC 和 Microsoft 的 cl.exe 编译器之间存在差异。

这是一个示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(void) {
    int i_max = INT_MAX;
    char c_max = CHAR_MAX, c;

    c = i_max;
    printf("i_max: %d, c_max: %d, c: %d\n", i_max, c_max, c);
    return EXIT_SUCCESS;
}

输出是:

i_max: 2147483647, c_max: 127, c: -1

正如您在上面的代码中看到的,我将一个 int 分配给一个 char。这不应该产生可能发生数据丢失的警告吗? Microsoft 的编译器(我已将其配置为非常严格)确实会发出警告,而 GCC 不会。

这是我使用的 GCC 选项:

-g -Werror -ansi -pedantic -Wall -Wextra

我是否缺少一些 GCC 选项以使编译时检查更加严格?

【问题讨论】:

    标签: c gcc mingw


    【解决方案1】:

    你在寻找

    -Wconversion
    

    您必须向 gcc 开发人员询问 -Wall-Wextra 中未包含某些警告的具体原因。

    无论如何,这些是我使用的标志:

    -Wall -Wextra -Wmissing-prototypes -Wmissing-declarations -Wshadow
    -Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Wnested-externs
    -Winline -Wno-long-long -Wconversion -Wstrict-prototypes
    

    正如其他人所指出的,-Wconversion 的行为已更改为 version 4.3 - 关于原型强制类型转换的旧警告现在可作为 -Wtraditional-conversion 使用。

    【讨论】:

    • gcc.gnu.org/onlinedocs/gcc/Warning-Options.html 此链接向您展示了Wall 和Wextra 中包含的。为什么 wconversion 不是一个完全的谜团/错误。
    • 我的观点是,这些警告在背后的痛苦远比它们捕捉到的东西要多得多,而且我对 gcc 政策决策的感觉是,它们也倾向于这样思考。当然,最好有一个 -W 选项,意思是“检查所有内容,无论多么烦人”。
    • 对我不起作用。在 foo.c 中使用“gcc -g -Werror -ansi -pedantic -Wall -Wextra -Wconversion foo.c”和上面的代码不会导致 gcc 4.1.2 的警告
    • @Glen:奇怪; mingw-gcc4.4.0 说warning: conversion to 'char' from 'int' may alter its value
    • 是的,看起来它以前只警告原型,而不是所有分配。
    【解决方案2】:

    我也没有收到-Wconversion 的警告/错误。但是,如果您通过 splint 之类的内容通过,您会收到三个警告:

    file.c: (in function main)
    file.c:9:5: Assignment of int to char: c = i_max
      To make char and int types equivalent, use +charint.
    file.c:10:52: Format argument 2 to printf (%d) expects int gets char: c_max
       file.c:10:32: Corresponding format code
    file.c:10:59: Format argument 3 to printf (%d) expects int gets char: c
       file.c:10:39: Corresponding format code
    
    Finished checking --- 3 code warnings
    

    如果您认真对待所有错误,则应该使用多个工具。

    【讨论】:

    • 请记住,对于像 printf() 这样的可变参数函数,char 将作为 int 传递,而 %d 是获取数值的正确格式说明符。 A %c 会将值打印为字符,区别在于“65”和“A”。
    • 正确(虽然,强制转换会使它变得明确,从而消除警告)。我的观点更倾向于这样一个事实,即在尝试关闭无错误/无错误代码时,多种观点很重要。
    【解决方案3】:

    你的问题有一点细微的差别,从措辞的方式对我来说并不是很明显。

    如果您认为 GCC(特别是 GCC)应该在此处发出警告,那么某些编译器选项可能会有所帮助(请参阅其他回复)。

    如果您认为 任何 编译器应该在这里发出警告(我似乎在您的问题中读到了这种情绪),那么......好吧,“警告”不是强制性的,甚至不是强制性的事实上统一。这里没有“应该”。在没有显式转换的情况下将较大类型的整数值分配给较小的类型在 C 中是完全合法的。转换时溢出,会产生实现定义的行为(甚至不是 UB :))

    【讨论】:

      【解决方案4】:

      -Wall doesn't quite mean -Wall,-Wextra 已经因为有点过于迂腐而受到抨击。

      正如 Christoph 所说,您正在寻找 -Wconversion。真正深入了解 -Wall 和 -Wextra 实际打开的内容,并且只需在 make 文件中指定所需的 -W 标志,尤其是在将警告视为错误时,这很好。

      【讨论】:

      • 如果您不喜欢有关签名比较的警告,请禁用它们;此外,对于遗留代码库来说,严格的警告可能是一个问题,但如果你从头开始,让你的代码没有警告真的不难——我猜有些人只是懒惰;)
      【解决方案5】:

      在 C 中,将 int 分配给 char 是合法的。

      由于它是合法的(但可能是狡猾的),不同的编译器供应商在遇到此代码时会做不同的事情。

      我猜 MS 只是过于迂腐,而 GCC 的家伙们认为它甚至不值得警告。

      【讨论】:

        【解决方案6】:

        我认为它属于“通常的算术转换”(6.3.1.8) 或“整数提升规则”(5.1.2.3 (?)),但我找不到说明您的行为的具体文本预计会看到。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-11
          • 2012-12-10
          • 2018-02-03
          • 1970-01-01
          • 2021-12-17
          • 2021-12-11
          • 1970-01-01
          相关资源
          最近更新 更多