printf + uint_64 на Солярисе 9?

У меня есть код c(++), который использует sprintf для преобразования uint_64 в строку. Это должно быть переносимо как на Linux, так и на Solaris.

В Linux мы используем %ju, но похоже, что в Solaris нет эквивалента. Самое близкое, что я могу найти, это %lu, но это приводит к неправильному выводу. Некоторый пример кода:

#include <stdio.h>
#include <sys/types.h>

#ifdef SunOS
typedef uint64_t u_int64_t;
#endif

int main(int argc, char **argv) {
    u_int64_t val = 123456789123L;

#ifdef SunOS
    printf("%lu\n", val);
#else
    printf("%ju\n", val);
#endif
}

В Linux результат такой, как и ожидалось; на Солярисе 9 (не спрашивайте) это "28"

Что я могу использовать?


person Kris Pruden    schedule 03.10.2008    source источник


Ответы (5)


Если у вас есть inttypes.h, вы можете использовать макросы, которые он предоставляет:

printf(  "%" PRIu64 "\n", val);

Не красиво (кажется, я часто говорю это в последнее время), но это работает.

person Michael Burr    schedule 03.10.2008

В системе, совместимой с C99:

#include <inttypes.h>

uint64_t big = ...;
printf("%" PRIu64 "\n", big);

См. раздел 7.8 стандарта C99.

Спецификаторы: {PRI,SCN}[diouxX]{N,LEASTN,MAX,FASTN,PTR}.

Где PRI для семейства printf(), SCN для семейства scanf(), d и i для целочисленных типов со знаком; o,u,x,X — целочисленные типы без знака, такие как восьмеричный, десятичный, шестнадцатеричный и шестнадцатеричный; N — одна из поддерживаемых ширин; LEAST и FAST соответствуют этим модификаторам; PTR для intptr_t; а MAX для intmax_t.

person wnoise    schedule 03.10.2008

Ответ зависит от того, является ли ваш код на самом деле C или C++. В C вы должны использовать unsigned long long, а не другой тип (это соответствует текущему стандарту, а long long довольно распространено, насколько это касается поддержки C99), добавлять ULL вместо L к вашей константе и использовать (как было упоминается) %llu в качестве вашего спецификатора. Если поддержка C99 не существует, вы можете проверить документацию компилятора, так как нет другого стандартного способа сделать это. long long гарантируется как минимум 64 бита.

person coppro    schedule 03.10.2008
comment
uint64_t каждый бит такой же стандартный, как unsigned long long. - person Jonathan Leffler; 03.10.2008

Вы можете использовать %llu для long long. Однако это также не очень переносимо, потому что long long не обязательно будет 64-битным. :-)

person Chris Jester-Young    schedule 03.10.2008

Вы можете получить uint64_t из stdint.h, если хотите избежать условного typedef SunOS.

person Ted Percival    schedule 03.10.2008
comment
Но вам также понадобится PRIu64 из ‹inttypes.h›, включая ‹stdint.h›. - person Jonathan Leffler; 03.10.2008