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.
Use format specifier %lu
instead of %d
and your compiler should stop complaining.
printf("Approximately %lu.%lu' of tape used\n", count/bpi/12, (count*10/bpi/12)%10);
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.
Use %lu
instead of %d
. %d
is used for type int
, %lu
for unsigned long
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With