unsigned int не является uint32_t при компиляции в cortex-m0 возможна проблема с флагом компилятора C

Мне нужно было портировать проект для работы с Eclipse с собственным Makefile. Я изменил его make-файл и думаю, что ошибка связана с ним или с флагом компилятора.

Хост: Virtualbox Win 8, x64, целевое устройство: nrf51822, которое представляет собой arm cortex-m0. Я использую кросс-компилятор gnu arm 4.8.4 (GNU Tools ARM Embedded)

Компиляция показывает следующее сообщение об ошибке/предупреждении:

src/main.c:173:4: error: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' [-Werror=format=]

Я этого не понимаю. uint32_t в данном случае — это unsigned int. Я включил stdint.h.

Я компилирую исходники со следующими флагами:

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

Разве -mcpu=cortex-m0 не указывает размер целого числа? Макросы препроцессора stdint.h должны генерировать «typedef unsigned int __uint32_t;». Eclipse показывает, что эта строка скомпилирована, но я не знаю, можно ли ей доверять, потому что внешний make-файл используется с собственным компилятором.


person Dati    schedule 25.08.2014    source источник
comment
Я не уверен в этом, но я думаю, что использование %u для uint32_t не определено, даже если оно имеет тот же размер, что и unsigned int. Таким образом, предупреждение может быть как-то оправдано (хотя его можно безопасно игнорировать).   -  person mafso    schedule 26.08.2014
comment
Предложите "%" PRIu32 вместо "%u".   -  person chux - Reinstate Monica    schedule 26.08.2014
comment
@mafso Нет, это не так, потому что а) это не undefined и б) определения типов - это просто псевдонимы, поэтому, если uint32_t действительно определяется как unsigned int, то они точно такого же типа. Я подозреваю, что OP ошибается и unsigned int не 32 бита. Печать sizeof(unsigned int) подтвердит.   -  person Jim Balter    schedule 26.08.2014
comment
@Jim Balter Printing sizeof(unsigned int) * CHAR_BIT подтвердит еще больше.   -  person chux - Reinstate Monica    schedule 26.08.2014
comment
Код публикации main.c:173 может помочь.   -  person chux - Reinstate Monica    schedule 26.08.2014
comment
@JimBalter: Объявление а) У вас есть источник для этого? sizeof(uint32_t) == sizeof(unsigned) не означает, что они являются псевдонимами, они оба могут быть определениями типов для какого-то встроенного типа, как я читал стандарт, и они оба могут быть разными типами (аналогично тому, как char может быть как signed char, но другого типа). Мне любопытно, будет ли оправдано такое предупреждение даже на системах с sizeof(uint32_t) == sizeof(unsigned int)...   -  person mafso    schedule 26.08.2014
comment
@mafso Нет, я перепутал с тем фактом, что вы можете передать положительный int в %u , но это потому, что int и unsigned int являются соответствующими типами. Стандарт действительно допускает несколько несовместимых целочисленных типов одного и того же размера, хотя я не думаю, что что-то подобное существует, и это кажется плохой идеей. аналогично тому, как char может быть похож на подписанный char, но другого типа, но в стандарте говорится, что реализация должна определять char так, чтобы он имел тот же диапазон, представление и поведение, что и подписанный char или неподписанный char, поэтому передача любого из них в %c безопасно.   -  person Jim Balter    schedule 26.08.2014
comment
Мне удалось запустить код: int k = sizeof(int); // равно 4 k = sizeof(unsigned int); // равно 4 k = sizeof(uint32_t); //is 4 k = sizeof(long int);//is 4 k = sizeof(short int);//is 2   -  person Dati    schedule 26.08.2014
comment
У меня есть пара предупреждений, подобных опубликованному, но код следующий: sprintf(buf,Error: %u %u %s\n\r,error_code, line_num,p_file_name); //которые являются uint32_t, uint32_t и const uint8_t *   -  person Dati    schedule 26.08.2014


Ответы (1)


uint32_t – это определение типа (псевдоним) для некоторого предопределенного целочисленного типа без знака. Этот тип гарантированно имеет ширину ровно 32 бита без дополнительных битов. Вы не можете с уверенностью предположить, что это псевдоним для какого-либо конкретного типа. Вероятно, это может быть либо unsigned int, либо unsigned long int. (Менее вероятно, что это может быть unsigned char или unsigned short в необычной системе, или это может быть расширенный целочисленный тип; это не может быть unsigned long long, который имеет ширину не менее 64 бит.)

Печать значения uint32_t с помощью "%u" непереносима. Вы можете сойти с рук, если ваша реализация определяет uint32_t как unsigned int (ваша, по-видимому, этого не делает). Вам вероятно это сойдет с рук, если unsigned int окажется 32-битным.

Правильный формат для uint32_t определяется как макрос в <inttypes.h>:

uint32_t x = 42;
printf("x = %" PRIu32 "\n", x);

(PRIu32 расширяется до строкового литерала; при этом используется тот факт, что соседние строковые литералы объединяются.)

Более простой способ — преобразовать значение в известный тип:

uint32_t x = 42;
printf("x = %ju\n", (intmax_t)x);

или возможно:

uint32_t x = 42;
printf("x = %llu\n", (unsigned long long)x);
person Keith Thompson    schedule 25.08.2014
comment
Я понимаю что ты имеешь ввиду. На самом деле мне удалось найти это в _default_types.h (включенном из stdint.h) typedef UINT32_TYPE __uint32_t; и похоже, что этот макрос установлен компилятором. - person Dati; 26.08.2014
comment
Как можно использовать PRIu32? Компилятор сообщает for: printf(x = % PRIu32 \n, (uint32_t)3); src/main.c:174:19: ошибка: ожидается ')' перед 'PRIu32' - person Dati; 26.08.2014
comment
@Дати: тебе нужно #include <inttypes.h> - person Keith Thompson; 26.08.2014