Предупреждение компиляции GCC: формат "% i" ожидает аргумент типа "int *", но аргумент 2 имеет тип "enum month *" [-Wformat] - PullRequest
0 голосов
/ 16 февраля 2012

При попытке скомпилировать код я получаю следующее предупреждение:

program141.c: 13: 5: предупреждение: формат «% i» ожидает аргумент типа «int *», но аргумент 2 имеет тип «enum month *» [-Wformat]

// Program to print the number of days in a month

#include <stdio.h>

int main (void)
{
    enum month { january = 1, february, march, april, may, june,
         july, august, september, october, november, december };
    enum month aMonth;
    int        days;

    printf ("Enter month number: ");
    scanf ("%i", &aMonth);

    switch (aMonth) {
    case january:
    case march:
    case may:
    case july:
    case august:
    case october:
    case december:
        days = 31;
        break;
    case april:
    case june:
    case september:
    case november:
        days = 30;
        break;
    case february:
        days = 28;
        break;
    default:
        printf ("bad month number\n");
        days = 0;
        break;
    }

    if ( days != 0 )
    printf ("Number of days is %i\n", days);

    if ( aMonth == february )
    printf ("...or 29 if it's a leap year\n");

    return 0;
}

Этот код взят из книги, которую я читаю.

Как мне исправить это предупреждение?

Ответы [ 4 ]

4 голосов
/ 16 февраля 2012

Спецификация преобразования %i, используемая с функцией scanf, соответствует указателю на целое число со знаком. В Си перечислимый тип - это целочисленный тип, определенный реализацией, совместимый с этим типом.

В gcc перечисления обычно имеют тип unsigned int и типа int, если в константах перечисления есть отрицательное значение.

См. gcc документация, определяемая реализацией для перечислений (выделено мое):

Целочисленный тип, совместимый с каждым перечисленным типом (C90 6.5.2.2, C99 6.7.2.2).

Обычно типом является unsigned int , если в перечислении нет отрицательных значений, в противном случае int. Если указано -fshort-enums, то при наличии отрицательных значений это первое из знаковых char, short и int, которые могут представлять все значения, в противном случае это первое из unsigned char, unsigned short и unsigned int, которое может представлять все ценности. В некоторых целях -fshort-enums является значением по умолчанию; это определяется ABI.

Источник http://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html

Чтобы исправить предупреждение в вашей системе, просто используйте спецификацию преобразования %u, которая соответствует указателю на целочисленный тип без знака:

scanf ("%u", &aMonth);
2 голосов
/ 16 февраля 2012

Тип, лежащий в основе конкретного перечисления, не обязательно int - реализации могут выбирать меньший тип, если подходят все значения (gcc сделает это, если вы включите -fshort-enums).

Для переносимого решения сделайте aMonth и int (любой другой целочисленный тип будет работать, пока вы используете правильный спецификатор преобразования) и приведите к enum month при необходимости.

2 голосов
/ 16 февраля 2012

Введите int, затем назначьте его enum month объекту

int temp;
scanf("%d", &temp);
/* make sure 1 <= temp <= 12 */
aMonth = temp;

Или вы можете попробовать приведение, но это небезопасно ( представлениеenum и int s не обязательно должны быть одинаковыми )

scanf("%d", (int*)&aMonth);

Примечание: спецификатор формата "%i" принимает значения в десятичном формате, шестнадцатеричные и восьмеричные обозначения.

2 голосов
/ 16 февраля 2012

Попробуйте с:

scanf ("%u", &aMonth);
...