Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unsigned int is not uint32_t when compile to cortex-m0 -- possible C compiler flag 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.

like image 493
Dati Avatar asked Aug 25 '14 21:08

Dati


1 Answers

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);
like image 173
Keith Thompson Avatar answered Oct 29 '22 20:10

Keith Thompson