GCC - не должно ли выдаваться предупреждение при присвоении int символу?

Недавно я установил на своем ноутбуке среду 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, чтобы сделать проверки времени компиляции еще строже?


person Ree    schedule 13.11.2009    source источник


Ответы (6)


Ты ищешь

-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 изменилось с версией 4.3 - старой предупреждение о прототипах, вызывающих преобразование типа, теперь доступно как -Wtraditional-conversion.

person Christoph    schedule 13.11.2009
comment
gcc.gnu.org/onlinedocs/gcc/Warning-Options.html Эта ссылка показывает, что входит в Wall и Wextra. Почему wconversion не является полной загадкой / ошибкой. - person Pod; 13.11.2009
comment
Мое мнение таково, что эти предупреждения гораздо чаще вызывают головную боль, чем что-то улавливают, и я считаю, что политические решения gcc таковы. Было бы неплохо иметь одну опцию -W, которая означала бы все проверять, конечно, независимо от того, насколько это раздражает. - person David Thornley; 13.11.2009
comment
у меня не работает. использование gcc -g -Werror -ansi -pedantic -Wall -Wextra -Wconversion foo.c с приведенным выше кодом в foo.c не приводит к предупреждению с gcc 4.1.2 - person Glen; 13.11.2009
comment
@Glen: странно; mingw-gcc4.4.0 говорит warning: conversion to 'char' from 'int' may alter its value - person Christoph; 13.11.2009
comment
@Christoph, я думаю, они добавили его после 4.1.2. Я пробовал это с вашими обновленными флагами, но все еще не получаю предупреждений. - person Glen; 13.11.2009
comment
Да, похоже, раньше он предупреждал только о прототипах, а не обо всех заданиях. - person Adam Goode; 13.11.2009
comment
@Martinho: Да, можно так подумать. Именно в этот момент я не могу понять команду gcc. - person David Thornley; 13.11.2009
comment
@Martinho - -W*all* было бы отличным вариантом для Unix, где оболочки выполняют подстановку. Я думаю, что всем будет очень весело с параметром компилятора, который меняется в зависимости от того, какой у вас текущий каталог. В соответствии с постоянно расширяющимися (по количеству и размеру) опциями GCC, как насчет опции -Wall-really-i-mean-all-of-them? - person Michael Burr; 13.11.2009

Я тоже не получал предупреждения / ошибки с -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

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

person ezpz    schedule 13.11.2009
comment
Имейте в виду, что для вариативной функции, такой как printf (), char будет передаваться как int, и что% d является правильным спецификатором формата для получения числового значения. % C распечатает значение как символ, разница в том, что между 65 и A. - person David Thornley; 13.11.2009
comment
Верно (хотя приведение сделало бы это явным и, таким образом, удалило бы предупреждение). Моя точка зрения была больше связана с тем, что при попытке закрыть код без ошибок / ошибок важны несколько точек зрения. - person ezpz; 13.11.2009

В вашем вопросе есть небольшой нюанс, который мне не сразу очевиден по формулировке.

Если вы считаете, что GCC (в частности, GCC) должен выдавать здесь предупреждение, возможно, вам могут помочь некоторые параметры компилятора (см. Другие ответы).

Если вы думаете, что любой компилятор должен выдавать здесь предупреждение (и я, кажется, прочитал это мнение в вашем вопросе), то ... ну, "предупреждения" никоим образом не являются обязательными или даже де-факто единый. Здесь нет «следует». Присвоение целочисленного значения с большим типом меньшему типу без явного приведения абсолютно законно в C. Переполнение при преобразовании дает поведение, определяемое реализацией (это даже не UB :))

person AnT    schedule 13.11.2009

-Wall не совсем означает -Wall, -Wextra уже находится под огнем за излишнюю педантичность.

Как сказал Кристоф, вы ищете -Wconversion. Хорошо разобраться в том, что на самом деле включают -Wall и -Wextra, и просто указать флаги -W, которые вы хотите использовать в своем файле make, особенно если рассматривать предупреждения как ошибки.

person Tim Post♦    schedule 13.11.2009
comment
если вам не нравятся предупреждения о сравнении подписей, отключите их; Кроме того, строгие предупреждения могут быть проблемой для устаревших баз кода, но если вы начнете с нуля, действительно не так уж и сложно сделать ваш код свободным от предупреждений - я думаю, некоторые люди просто ленивы;) - person Christoph; 13.11.2009

В C присвоение int типу char допустимо.

Поскольку это законно (но, возможно, хитро), разные поставщики компиляторов делают разные вещи, когда сталкиваются с этим кодом.

Я предполагаю, что MS просто чрезмерно педантичен, в то время как парни из GCC решили, что это даже не заслуживает предупреждения.

person Glen    schedule 13.11.2009

Я думаю, что это подпадает под «Обычные арифметические преобразования» (6.3.1.8) или «Правила целочисленного продвижения» (5.1.2.3 (?)), Но я не могу найти конкретный текст, в котором говорится, что наблюдаемое вами поведение является ожидаемым. .

person pmg    schedule 13.11.2009