Как бороться с предупреждениями -Wconversion от GCC? - PullRequest
5 голосов
/ 29 октября 2009

Я строю свой проект с флагом предупреждения GCC -Wconversion. (gcc (Debian 4.3.2-1.1) 4.3.2) в 64-битной операционной системе GNU / Linux / Hardware. Я нахожу это полезным для определения, где я смешал типы или потерял ясность относительно того, какие типы следует использовать.

Это не так полезно в большинстве других ситуаций, которые активируют свои предупреждения, и я спрашиваю, как я собираюсь иметь дело с этими:

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

В связи с неожиданными результатами вышеприведенных тестов (случаи a и c) я также прошу объяснить и эти различия.

Редактировать: И не слишком ли сложно применить все это с (char), чтобы предотвратить предупреждение?

Edit2: некоторые дополнительные случаи (следующие из вышеупомянутых случаев):

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

Кроме того, то, что я спрашиваю, субъективно, и я хотел бы услышать, как другие люди обращаются с предупреждениями о конверсиях в подобных случаях, если учесть, что некоторые разработчики рекомендуют удалить все предупреждения.

Yae:

Одним из возможных решений является использование int с вместо char с, верно? Ну, на самом деле, он не только требует больше памяти, но и медленнее, что можно продемонстрировать с помощью следующего кода. Математические выражения предназначены только для получения предупреждений при построении с -Wconversion. Я предполагал, что версия, использующая переменные char, будет работать медленнее, чем та, которая использует int s из-за преобразований, но в моей (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;
}

Передайте -DUSE_INT в gcc для создания версии int из приведенного выше фрагмента.

Ответы [ 2 ]

2 голосов
/ 29 октября 2009

Когда вы говорите /* 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 не выдаст предупреждение. Это потому, что присвоение a допустимо, a - это char, и ваша задача (не компилятор) - убедиться, что математика не переполняется во время выполнения.

0 голосов
/ 29 октября 2009

Может быть, компилятор уже может видеть, что все значения вписываются в символ, поэтому он не мешает предупреждению. Я ожидал бы, что enum будет решен в самом начале компиляции.

...