Issue
I've needed to port a project to run with Eclipse with its own Makefile. I have modified its makefile, and i guess the error is connected to it or a compiler flag.
Host: Virtualbox Win 8,x64, target device: nrf51822 which is arm cortex-m0. I use gnu arm cross compiler 4.8.4 (GNU Tools ARM Embedded)
Compile shows the following error/warning message:
src/main.c:173:4: error: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' [-Werror=format=]
I don't understand it. uint32_t is unsigned int in this case. I've included stdint.h.
I compile sources with the following flags:
CFLAGS += -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu11 -funsigned-char -DNRF51 -DDEBUG_NRF_USER -DBLE_STACK_SUPPORT_REQD -DBOARD_PCA10000 -DNRF51822_QFAA_CA
CFLAGS += -Wall -Werror
CFLAGS += -mfloat-abi=soft
Does not -mcpu=cortex-m0 specifies the size of the integer? stdint.h pre-processor macros should generate "typedef unsigned int __uint32_t;". Eclipse shows it that this line is compiled, but i do not know wether to trust it because external makefile is used with its own compiler.
Solution
uint32_t
is a typedef (an alias) for some predefined unsigned integer type. That type is guaranteed to be exactly 32 bits wide, with no padding bits. You cannot safely assume that it's an alias for any particular type. It could plausibly be either unsigned int
or unsigned long int
. (Less plausibly, it could be unsigned char
or unsigned short
on an unusual system, or it could be an extended integer type; it cannot be unsigned long long
, which is at least 64 bits wide.)
If your implementation has more than one 32-bit unsigned integer type with no padding bits, uint32_t
could be any of them, at the whim of the implementer.
Printing a uint32_t
value with "%u"
is non-portable. You can get away with it if your implementation happens to define uint32_t
as unsigned int
(yours apparently does not). You can probably get away with it if unsigned int
happens to be 32 bits.
The correct format for uint32_t
is defined as a macro in <inttypes.h>
:
uint32_t x = 42;
printf("x = %" PRIu32 "\n", x);
(PRIu32
expands to a string literal; this takes advantage of the fact that adjacent string literals are concatenated.)
An easier way is to convert the value to a known type:
uint32_t x = 42;
printf("x = %ju\n", (intmax_t)x);
or perhaps:
uint32_t x = 42;
printf("x = %llu\n", (unsigned long long)x);
Answered By - Keith Thompson Answer Checked By - Senaida (WPSolving Volunteer)