Чистый код к printf size_t в C++ (или: Ближайшая альтернатива %z C99 в C++)

Во многих приложениях найдите, означает, "находят на текущей странице/экране", в то время как поиск означает "поиск вся база данных/Интернет". Веб-браузеры, справка онлайн и другие приложения, кажется, делают это различие.

94
задан Justin L. 10 October 2009 в 01:51
поделиться

5 ответов

У большинства компиляторов есть свой собственный спецификатор для аргументов size_t и ptrdiff_t , Visual C ++, например, использует% Iu и% Id соответственно, я думаю, что gcc позволит вам использовать% zu и% zd.

Вы можете создать макрос:

#if defined(_MSC_VER) || defined(__MINGW32__) //__MINGW32__ should goes before __GNUC__
  #define JL_SIZE_T_SPECIFIER    "%Iu"
  #define JL_SSIZE_T_SPECIFIER   "%Id"
  #define JL_PTRDIFF_T_SPECIFIER "%Id"
#elif defined(__GNUC__)
  #define JL_SIZE_T_SPECIFIER    "%zu"
  #define JL_SSIZE_T_SPECIFIER   "%zd"
  #define JL_PTRDIFF_T_SPECIFIER "%zd"
#else
  // TODO figure out which to use.
  #if NUMBITS == 32
    #define JL_SIZE_T_SPECIFIER    something_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_signed
    #define JL_PTRDIFF_T_SPECIFIER something_signed
  #else
    #define JL_SIZE_T_SPECIFIER    something_bigger_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_bigger_signed
    #define JL_PTRDIFF_T_SPECIFIER something-bigger_signed
  #endif
#endif

Использование:

size_t a;
printf(JL_SIZE_T_SPECIFIER, a);
printf("The size of a is " JL_SIZE_T_SPECIFIER " bytes", a);
60
ответ дан 24 November 2019 в 06:06
поделиться

Эффективный тип, лежащий в основе size_t, зависит от реализации . Стандарт C определяет его как тип, возвращаемый оператором sizeof; помимо беззнакового и своего рода интегрального типа, size_t может быть практически любым, размер которого может вместить наибольшее значение, которое, как ожидается, будет возвращено функцией sizeof ().

Следовательно, строка формата, которая будет использоваться для size_t, может варьироваться в зависимости от на сервере. Он всегда должен иметь "u", но может быть l или d или, может быть, что-то еще ...

Уловка может состоять в том, чтобы преобразовать его в самый большой интегральный тип на машине, гарантируя отсутствие потерь при преобразовании, а затем с использованием строки формата, связанной с этим известным типом.

3
ответ дан 24 November 2019 в 06:06
поделиться

Поскольку вы используете C ++, почему бы не использовать IOStreams? Это должно компилироваться без предупреждений и делать правильные вещи с учетом типов, если вы не используете безумную реализацию C ++, которая не определяет оператор << для size_t .

Когда фактический вывод должен выполняться с помощью printf () , вы все равно можете комбинировать его с IOStreams, чтобы получить безопасное поведение типов:

size_t foo = bar;
ostringstream os;
os << foo;
printf("%s", os.str().c_str());

Это не суперэффективно, но ваш случай выше относится к файловому вводу-выводу, так что это ваше узкое место, а не код форматирования строки.

10
ответ дан 24 November 2019 в 06:06
поделиться

вот возможное решение, но оно не совсем красивое ..

template< class T >
struct GetPrintfID
{
  static const char* id;
};

template< class T >
const char* GetPrintfID< T >::id = "%u";


template<>
struct GetPrintfID< unsigned long long > //or whatever the 64bit unsigned is called..
{
  static const char* id;
};

const char* GetPrintfID< unsigned long long >::id = "%lu";

//should be repeated for any type size_t can ever have


printf( GetPrintfID< size_t >::id, sizeof( x ) );
7
ответ дан 24 November 2019 в 06:06
поделиться

Спецификатор формата printf % zu будет нормально работать в системах C ++; нет необходимости усложнять его.

67
ответ дан 24 November 2019 в 06:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: