В настоящее время я работаю над программным проектом в C, который должен работать на различных платформах. Я стараюсь оставаться как можно ближе к стандарту C90, но вам нужны некоторые поддерживаемые расширения, такие как stdint.h и unsigned long long type. Я намеренно не хочу «возвращаться» к стандарту C99, так как некоторые из компиляторов, которые я использую, не поддерживают все функции C99, такие как смешанные декларации и код и т. Д.Формат size_t с gcc std = gnu90
Таким образом, я в настоящее время компилирую весь свой код с помощью gcc on мой (64-разрядный Ubuntu) с -Wall -Wextra -pedantic -std=gnu90
(а не C90 из-за моего использования беззнакового длинного длинного и т. д., как описано выше) для решения всех нестандартных компонентов кода. До сих пор я мог адаптировать свой код, чтобы избавиться от всех предупреждений, но один: я не могу найти подходящий (printf) формат для size_t, который не дает предупреждения от gcc. Рассмотрим следующий пример кода, который иллюстрирует большинство вещей, которые я пробовал:
#include <stdint.h>
#include <stdio.h>
int main()
{
printf("%zu", sizeof(int)); /* C99 format specifier for size_t */
printf("%u", sizeof(int)); /* Treat size_t as unsigned int */
printf("%lu", sizeof(int)); /* Treat size_t as unsigned long int (only works when size_t is "typedef"ed to unsigned long int) */
return 0;
}
При компиляции с -Wall -Wextra -pedantic -std=gnu90
, я получаю предупреждения для первых двух строк:
test.c: 6: 3: предупреждение: ISO C90 не поддерживает модификатор длины 'z' gnu_printf [-Wformat =] test.c: 7: 3: warning: format '% u' ожидает аргумент типа unsigned int, но аргумент 2 имеет тип ' long unsigned int '[-Wformat =]
Хотя я не получаю предупреждение для третьей строки, это касается только моей системы разработки. В других системах, особенно на тех, где size_t является некоторым «обычным» типом или не «typedef» ed как unsigned long long, все равно будет предупреждение.
Мне хорошо известно, что в C90 нет спецификатора формата для size_t, но есть один в C99. Тем не менее, я думал, что установка -std=gnu90
даст мне спецификатор формата «z», но это предположение оказалось неправильным.
Поскольку я не мог избавиться от предупреждения (ы), я попытался определить спецификатор формата с некоторыми определениями препроцессора, как это:
#include <inttypes.h>
#include <stdio.h>
#ifdef __GNUC__
#define GLUE(x, y, z) x##y##z
#define GLUE_FORMAT(prefix, size) GLUE(PRI, prefix, size)
#define UINT_FORMAT(size) GLUE_FORMAT(u, size)
#define SIZE_T_FORMAT UINT_FORMAT(__SIZEOF_SIZE_T__)
#else /* C99 fall-back */
#define SIZE_T_FORMAT "zu"
#endif
int main()
{
printf("%" SIZE_T_FORMAT, sizeof(int));
return 0;
}
Я подумал, что это должно дать мне правильный спецификатор формата, единственным ограничением является то, что size_t не имеет знака (который он находится на всех моих целевых платформах до сих пор). Однако, это не работает, либо:
test.c: 15: 3: предупреждение: формат '% и' ожидает аргумент типа 'неподписанных INT', но аргумент 2 имеет тип 'длинный неподписанных Int' [- Wformat =]
есть ли способ, учитывая ограничения, чтобы преодолеть это предупреждение (или найти более элегантное решение, не прибегая к -std=c99
)?
Как насчет "% lu"? – Coconop
@Coconop:% lu будет работать на моей платформе разработки, но не на некоторых других –
@Coconop: Я добавил короткое объяснение к своему оригинальному сообщению и обновил код. –