1
votes

I get the following warning when I try to compile the code:

program141.c:13:5: warning: format ‘%i’ expects argument of type ‘int *’, but argument 2 has type ‘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;
}

This code is from a book I'm reading.

How do I fix this warning?

4

4 Answers

3
votes

Try with:

scanf ("%u", &aMonth);
4
votes

The %i conversion specification used with the scanf function matches a pointer to a signed integer. In C, an enumerated type is an implementation defined integer type compatible with that type.

In gcc, enums are normally of type unsigned int and of type int if there is a negative value in the enum constants.

See gcc implementation defined documentation on enums (emphasis mine):

The integer type compatible with each enumerated type (C90 6.5.2.2, C99 6.7.2.2).

Normally, the type is unsigned int if there are no negative values in the enumeration, otherwise int. If -fshort-enums is specified, then if there are negative values it is the first of signed char, short and int that can represent all the values, otherwise it is the first of unsigned char, unsigned short and unsigned int that can represent all the values. On some targets, -fshort-enums is the default; this is determined by the ABI.

Source http://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html

To fix the warning on your system, just use the %u conversion specification that matches a pointer to an unsigned integer type:

scanf ("%u", &aMonth);
2
votes

Input an int, than assign it to the enum month object

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

Or you can try a cast, but it is not safe (the representation of the enum and ints need not be the same)

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

Note: the format specifier "%i" accepts values in decimal, hexadecimal, and octal notations.

2
votes

The type underlying a particular enumeration isn't necessarily int - implementations are free to choose a smaller type as long as all values fit (gcc will do this if you enable -fshort-enums).

For a portable solution, make aMonth an int (any other integer type will do as long as you use the correct conversion specifier) and cast to enum month as necessary.