2015-04-03 6 views
1

В настоящее время я работаю над программным проектом в 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)?

+2

Как насчет "% lu"? – Coconop

+0

@Coconop:% lu будет работать на моей платформе разработки, но не на некоторых других –

+0

@Coconop: Я добавил короткое объяснение к своему оригинальному сообщению и обновил код. –

ответ

1

Вы считаете отливку? Литье обычно является признаком проблем, но в какой-то момент может быть проще просто написать

printf("%u", (unsigned) sizeof(int)); 

Вы могли бы даже объединить бросок в макро

#define usizeof(a) ((unsigned)sizeof(a)) 
printf("%u", usizeof(int)); 

что сделает его достаточно легко использовать ,

+0

Чтобы рассказать о моих комментариях выше относительно этого предложения: это хорошо для некоторых систем, но если size_t «typedef» ed как unsigned long long, это может вызвать проблемы из-за downcast. –

+1

@AndreasUnterweger доводится до максимума (установите свои заголовки так, чтобы максимальный тип int и его формат printf были доступны) –

+0

@MattMcNabb: Это хорошая идея. Я попробую. –