5

我正在使用 GCC 的 -Wconversion 警告标志构建我的项目。(gcc (Debian 4.3.2-1.1) 4.3.2) 在 64 位 GNU/Linux 操作系统/硬件上。我发现它有助于确定我在哪里混合了类型或不清楚应该使用哪些类型。

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

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 */

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

(char)编辑:将所有这些都用于防止警告是否过度设计?

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

a += A;         /* warning converting from int to char */
a++;            /* ok */
a += (char)1;   /* warning converting from int to char */

除此之外,我要问的是主观的,当您认为某些开发人员主张删除所有警告时,我想听听其他人在此类情况下如何处理转换警告。

耶:

一种可能的解决方案是只使用ints 而不是chars 对吗?实际上,它不仅需要更多内存,而且速度也较慢,如以下代码所示。数学表达式只是为了在使用-Wconversion. 由于转换,我假设使用char变量的版本会比使用 s 的版本运行得慢,但在我的(64 位双核 II)系统上,版本更慢。intint

#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;
}

传递-DUSE_INT给 gcc 以构建上述代码段的 int 版本。

4

2 回答 2

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)

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

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

于 2009-10-29T14:14:13.933 回答
0

也许编译器已经可以看到所有值都适合一个字符,所以它不会打扰警告。我希望enum在编译开始时就可以解决。

于 2009-10-29T13:05:00.030 回答