如何处理海湾合作委员会的-Wconversion警告?

Jam*_*ris 5 c gcc compiler-warnings

我正在用GCC的-Wconversion警告标志构建我的项目.(gcc(Debian 4.3.2-1.1)4.3.2)在64位GNU/Linux OS /硬件上.我发现它有助于确定我混合类型的位置或者应该使用哪种类型的清晰度.

在大多数激活它的警告的其他情况下它并没有那么有用,我问我打算如何处理这些问题:

enum { A = 45, B, C };   /* fine */

char a = A;              /* huh? seems to not warn about A being int. */
char b = a + 1;          /* warning converting from int to char */
char c = B - 2;          /* huh? ignores this *blatant* int too.*/
char d = (a > b ? b : c) /* warning converting from int to char */
Run Code Online (Sandbox Code Playgroud)

由于上述测试(案例ac)的意外结果,我也要求解释这些差异.

编辑:(char)为了防止警告,是否过度工程化所有这些?

Edit2:一些额外案例(继上述案例之后):

a += A;         /* warning converting from int to char */
a++;            /* ok */
a += (char)1;   /* warning converting from int to char */
Run Code Online (Sandbox Code Playgroud)

除此之外,我所要求的是主观的,我想听听其他人在你认为某些开发人员主张删除所有警告时如何处理转换警告.

YAE:

一种可能的解决方案是使用ints而不是chars?实际上,它不仅需要更多内存,而且速度也更慢,如下面的代码所示.数学表达式只是用于构建时获取警告-Wconversion.我认为使用char变量的版本比使用ints 的版本运行速度慢,但是在我的(64位双核II)系统上,int版本速度较慢.

#include <stdio.h>

#ifdef USE_INT
typedef int var;
#else
typedef char var;
#endif

int main()
{
    var start = 10;
    var end = 100;
    var n = 5;
    int b = 100000000;
    while (b > 0) {
        n = (start - 5) + (n - (n % 3 ? 1 : 3));
        if (n >= end) {
            n -= (end + 7);
            n += start + 2;
        }
        b--;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

传递-DUSE_INT给gcc来构建上述代码片段的int版本.

Rob*_*ier 2

当你说/* int */你的意思是它正在向你发出警告吗?在使用 gcc 4.0.1 或 4.2.1 的这段代码中,我根本没有看到任何警告-Wconversion。编译器正在将这些枚举转换为常量。由于一切在编译时都是已知的,因此没有理由生成警告。编译器可以优化掉所有的不确定性(以下是Intel用4.2.1):

    movb    $45, -1(%rbp)    # a = 45
    movzbl  -1(%rbp), %eax
    incl    %eax
    movb    %al, -2(%rbp)    # b = 45 + 1
    movb    $44, -3(%rbp)    # c = 44 (the math is done at compile time)
    movzbl  -1(%rbp), %eax   
    cmpb    -2(%rbp), %al
    jle     L2               
    movzbl  -2(%rbp), %eax
    movb    %al, -17(%rbp)
    jmp     L4
L2: 
    movzbl  -3(%rbp), %eax
    movb    %al, -17(%rbp)
L4:
    movzbl  -17(%rbp), %eax
    movb    %al, -4(%rbp)    # d = (a > b ? b : c)
Run Code Online (Sandbox Code Playgroud)

这是没有打开优化的情况。通过优化,它将在编译时为您计算 b 和 d 并硬编码它们的最终值(如果它确实需要它们)。关键是 gcc 已经确定这里不会有问题,因为所有可能的值都适合char.

编辑:让我稍微修改一下。的赋值中可能存在错误b,并且编译器永远不会捕获它,即使它是确定的。例如,如果b=a+250;,那么这肯定会溢出,b但 gcc 不会发出警告。这是因为对 的赋值a是合法的,a是 a char,并且确保数学在运行时不会溢出是您的问题(而不是编译器的问题)。