Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't gcc -Wformat warn about printf %d on an unsigned int?

The following program has undefined behavior:

#include <stdio.h>

int main(void)
{
    unsigned int x = -100; // This is fine, becomes UINT_MAX - 100
    printf("%d\n", x); // This is undefined behavior.
    return 0;
}

C99 7.19.6.1p8 states %d expects an int argument.

C99 7.19.6.1p9 states "If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."

However, gcc -Wformat (which is included with -Wall) will not complain about the above program, why? Is this a bug, or a deliberate omission?

From the gcc manpage:

-Wformat

Check calls to "printf" and "scanf", etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense

like image 215
Chris Young Avatar asked Jul 03 '12 02:07

Chris Young


People also ask

What happens when you cast signed to unsigned in C?

Well the basic answer is – nothing. No bits are changed, the compiler just treats the bit representation as unsigned. For example, let us assume that the compiler represents signed integers using 2's complement notation (this is the norm – but is *not* mandated by the C language).

Is unsigned int better to use?

The Google C++ style guide recommends avoiding unsigned integers except in situations that definitely require it (for example: file formats often store sizes in uint32_t or uint64_t -- no point in wasting a signedness bit that will never be used).

What happens when an unsigned int goes negative C++?

An int is signed by default, meaning it can represent both positive and negative values. An unsigned is an integer that can never be negative. If you take an unsigned 0 and subtract 1 from it, the result wraps around, leaving a very large number (2^32-1 with the typical 32-bit integer size).

Can int be unsigned?

The 32-bit unsigned int data type can hold integer values in the range of 0 to 4,294,967,295. You may also refer to this data type simply as unsigned.


1 Answers

My best guess is that the warning is skipped because the UB is arguably invoked by the value and not merely by the type. va_arg allows the signedness to mismatch as long as the value is representable in both the signed and unsigned type. However, printf and friends are not specified in terms of va_arg and the standard states that any type mismatch results in UB, but this is probably a bug in the standard. Otherwise, printf("%x",1); would invoke UB. See my question on the topic:

Does printf("%x",1) invoke undefined behavior?

like image 141
R.. GitHub STOP HELPING ICE Avatar answered Sep 18 '22 08:09

R.. GitHub STOP HELPING ICE