is this compiler diagnostic legal?

R

Rainer Zufall

consider this code

#include <stdio.h>
int main(void)
{
unsigned long ul = 42;
printf("0x%08lX\n", ul);
return 0;
}

One compiler I tried issues the following diagnostic:

Warning foo.c: 5 printf argument mismatch for format X. Expected long int got unsigned long
0 errors, 1 warning

I always thought %X requires an unsigned quantity.

Who is right here, my understanding of the standard, or the compiler?
 
M

Martin

I always thought %X requires an unsigned quantity.

%lX converts a long argument into an unsigned long then to an unsigned
sequence of (in the case of %08lX) at least 8 hexadecimal digits,
padded with leading zeros if necessary.

The compiler is correct.
 
W

Walter Roberson

On Feb 11, 1:38=A0pm, Rainer Zufall <[email protected]>
wrote:
%lX converts a long argument into an unsigned long then to an unsigned
sequence of (in the case of %08lX) at least 8 hexadecimal digits,
padded with leading zeros if necessary.

C89 4.9.6.1 The fprintf Function

o,u,x,X The unsigned int argument is converted to unsigned octal (o),
unsigned decimal (u), or unsigned hexadecimal notation
(x or X) [...]
 
R

Robert Gamble

consider this code

#include <stdio.h>
int main(void)
{
unsigned long ul = 42;
printf("0x%08lX\n", ul);
return 0;
}

One compiler I tried issues the following diagnostic:

Warning foo.c: 5 printf argument mismatch for format X. Expected long int got unsigned long
0 errors, 1 warning

I always thought %X requires an unsigned quantity.

Who is right here, my understanding of the standard, or the compiler?

%X does always require an unsigned type, %lX requires a type of
unsigned long which you properly provided. You are correct, your
compiler is wrong.
 
M

Martin

I always thought %X requires an unsigned quantity.

Who is right here, my understanding of the standard, or the compiler?


I've looked into this after seeing the previous replies.

Plauger in "The Standard C Library" states that the four conversion
specifiers lo, lX, lx, and lu expect long arguments, which are then
converted to unsigned long.

K&R2 states that o, x, X, u expect the argument type to be int (i.e.,
signed) - although the errata for that book corrects that to unsigned
int. That implies lx expects the argument type to be unsigned long.

However, the most important resource, the C Standard, specifies
clearly that unsigned long is indeed the expected argument type for
the conversion specifiers, including the one you queried.

The compiler has got it wrong.

I shall annotate Plauger accordingly.
 
K

Keith Thompson

Martin said:
%lX converts a long argument into an unsigned long then to an unsigned
sequence of (in the case of %08lX) at least 8 hexadecimal digits,
padded with leading zeros if necessary.

The compiler is correct.

For context, the code was:

#include <stdio.h>
int main(void)
{
unsigned long ul = 42;
printf("0x%08lX\n", ul);
return 0;
}

and the warning was:

Warning foo.c: 5 printf argument mismatch for format X. Expected long int got unsigned long
0 errors, 1 warning

The format requires an unsigned long argument. The compiler's warning
is incorrect. This isn't actually a violation of the standard; the
standard allows additional diagnostics, and doesn't require them to be
factually correct. But it's certainly a bug.

If the actual argument were of type signed long, a compiler could
reasonably refrain from warning about it, but it cannot reasonably
warn about this call, which is perfectly correct.
 
H

Hans Schneider

consider this code

#include <stdio.h>
int main(void)
{
unsigned long ul = 42;
printf("0x%08lX\n", ul);
return 0;
}

One compiler I tried issues the following diagnostic:

Warning foo.c: 5 printf argument mismatch for format X. Expected long int got unsigned long
0 errors, 1 warning

I always thought %X requires an unsigned quantity.

Who is right here, my understanding of the standard, or the compiler?

LCC-WIN32 shows this warning also, but I think it has more sense.

unsigned long is always positive.

signed long can positive or negative be.

What if I want to print negative numbers in HeX?
 
K

Keith Thompson

Hans Schneider said:
Am Mon, 11 Feb 2008 14:38:16 +0100 (CET), Rainer Zufall


LCC-WIN32 shows this warning also, but I think it has more sense.

Since there's nothing wrong with the code, I hope lcc-win32 doesn't
show a warning for it.
unsigned long is always positive.

signed long can positive or negative be.

What if I want to print negative numbers in HeX?

There's no direct way to do that using printf.

If x is your number, you could do something like this:

printf("x = %s0x%x\n",
x < 0 ? "-" : "",
(unsigned)abs(x));

but it's not guaranteed to work for x == INT_MIN.
 
J

jacob navia

Hans said:
LCC-WIN32 shows this warning also, but I think it has more sense.

Not in the latest version. We had a discussion about this some months
ago and I fixed it, as far as I can remember. In any case I see
absolutely no warning with the latest version of lcc-win
 
P

Peter Nilsson

Robert Gamble said:
%X does always require an unsigned type, %lX requires a
type of unsigned long...

%X requires unsigned int, but observe that %hX requires
the promoted type of unsigned short, which may be int.
 
T

Thad Smith

Robert said:
%X does always require an unsigned type, %lX requires a type of
unsigned long which you properly provided.

That is what I expect, but the Standard is amazingly ambiguous:

7.9.6.1, p7:
The length modifiers and their meanings are:
....
l (ell) Specifies that a following d, i, o, u, x, or X conversion specifier
applies to a long int or unsigned long int argument; ...

Whose choice is it whether it should be long int or unsigned long int?

Then p8:
The conversion specifiers and their meanings are:
....
o,u,x,X The unsigned int argument is converted to unsigned octal (o),
unsigned decimal (u), or unsigned hexadecimal notation (x or X) in the
style dddd; ...

Here the X specifier says that it requires an unsigned int argument with no
mention of an alternative, no mention of arument type for %lX, so someone
has to choose whether the argument is an long int or unsigned long int and
on what basis?

This is a where I think I know the intent, but have a hard time proving it
with the wording in the Standard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top