简体   繁体   中英

Re Legacy code : format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘long unsigned int’ [-Wformat]

I often try to build a lot of old simulator and disk and tape archive tools, with recent GCC. Some errors are easy to fix, but I'm not so good a programmer.

I get :

itstar.c: In function 'addfiles':
itstar.c:194:4: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat]
itstar.c:194:4: warning: format '%d' expects argument of type 'int', but argument 3 has type 'long unsigned int' [-Wformat]

from this code fragment :

/* add files to a DUMP tape */
/* output buffer must have been initialized with resetbuf() */
static void addfiles(int argc,char **argv)
{
    int c=argc;
    char **v=argv;

    while(c--) {
        addfile(argc,argv,*v++);
    }
    if(verify)
        printf("Approximately %d.%d' of tape used\n",count/bpi/12,
            (count*10/bpi/12)%10);
}

Where line 194 is the third from last, beginning with printf.

The file is itstar.c, from tapetools, code here .

It builds despite the warning, but I prefer to know how to prevent it,
so the result is more efficient and there is less chance of data corruption.

Please, what have I missed, and need to change ?

Thank you in advance.

This is undefined behavior , which means anything can happen including appearing to work correctly and then break later on down the road.

Looking at the source we can see both count and bpi are unsigned long :

extern unsigned long bpi; /* tape density in bits per inch */
extern unsigned long count; /* count of tape frames written */ 

the correct format specifier for these would be %lu .

The first argument to printf specifies a string to print out which can contain conversion specifiers beginning with % that usually specifies the types of the subsequent arguments, so in your example:

"Approximately %d.%d' of tape used\n"
               ^^ ^^
               1  2

both conversion specifiers 1 and 2 are %d which means that printf will expect the next two arguments to be of type int but they are really of type unsigned long .

If we look at the draft C99 standard section 7.19.6.1 The fprintf function which also covers printf for format specifiers, says:

If a conversion specification is invalid, the behavior is undefined. 248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

so you need to fix the format specifier which is incorrect and your warning will go away and you will be back in well defined behavior land.

使用格式说明符%lu而不是%d ,您的编译器应该停止抱怨。

printf("Approximately %lu.%lu' of tape used\n", count/bpi/12, (count*10/bpi/12)%10);

Use %lu instead of %d . %d is used for type int , %lu for unsigned long .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM