У меня есть код C ++, который печатает size_t
:
size_t a;
printf("%lu", a);
Я бы хотел, чтобы это скомпилировалось без предупреждений как на 32-, так и на 64-битных архитектурах.
Если бы это был C99, я бы мог использовать printf("%z", a);
. Но AFAICT %z
не существует ни на одном стандартном диалекте C ++. Так что вместо этого я должен сделать
printf("%lu", (unsigned long) a);
что действительно некрасиво.
Если в языке нет size_t
встроенных средств для печати s, мне интересно, можно ли написать оболочку printf или что-то подобное, которое будет вставлять соответствующие приведения в size_t
s, чтобы устранить ложные предупреждения компилятора, сохраняя при этом хорошие.
Любые идеи?
Изменить Чтобы прояснить, почему я использую printf: у меня относительно большая база кода, которую я очищаю. Он использует оболочки printf, чтобы делать такие вещи, как «написать предупреждение, записать его в файл и, возможно, выйти из кода с ошибкой». Я мог бы собрать достаточно C ++ - foo, чтобы сделать это с помощью оболочки cout, но я бы предпочел не изменять каждый вызов warn () в программе, просто чтобы избавиться от некоторых предупреждений компилятора.
"%l"
? Разве это не всегда будет правильный размер? Или имеет значение мобильность?Ответы:
У большинства компиляторов есть свои собственные спецификаторы
size_t
иptrdiff_t
аргументы, например, Visual C ++ использует% Iu и% Id соответственно, я думаю, что gcc позволит вам использовать% zu и% zd.Вы можете создать макрос:
Использование:
источник
%z
поддерживается или нет , зависит от среды выполнения, а не компиляции. Используя__GNUC__
поэтому немного проблемы, если смешать GCC / MinGW с MSVCRT (и без использования дополненного Printf MinGW в).Спецификатор
printf
формата%zu
отлично работает в системах C ++; нет необходимости усложнять его.источник
C ++ 11
C ++ 11 импортирует C99, поэтому
std::printf
должен поддерживать%zu
спецификатор формата C99 .C ++ 98
На большинстве платформ
size_t
иuintptr_t
эквивалентны, и в этом случае вы можете использоватьPRIuPTR
макрос, определенный в<cinttypes>
:Если вы действительно хотите быть в безопасности,
uintmax_t
примените и используйтеPRIuMAX
:источник
В windows и реализация printf в Visual Studio
работает для меня. см. msdn
источник
VS 2008
. Кроме того, имейте в виду , что можно использовать%Id
,%Ix
и%IX
тоже.Поскольку вы используете C ++, почему бы не использовать IOStreams? Это должно компилироваться без предупреждений и делать правильные вещи с учетом типов, если вы не используете безумную реализацию C ++, которая не определяет
operator <<
forsize_t
.Когда фактический вывод должен быть выполнен с помощью
printf()
, вы все равно можете объединить его с IOStreams, чтобы получить безопасное поведение:Это не суперэффективно, но ваш случай, приведенный выше, касается файлового ввода-вывода, так что это ваше узкое место, а не этот код форматирования строки.
источник
std::stringstream
вместо потоков ввода-вывода.printf("x=%i, y=%i;\n", x, y);
противcout << "x=" << x << ", y=" << y << ";" << std::endl;
.вот возможное решение, но оно не совсем красивое ..
источник
Библиотека fmt обеспечивает быструю переносимую (и безопасную) реализацию,
printf
включающуюz
модификатор дляsize_t
:В дополнение к этому он поддерживает синтаксис строки формата, подобный Python, и фиксирует информацию о типе, поэтому вам не нужно вводить ее вручную:
Он был протестирован с основными компиляторами и обеспечивает согласованный вывод на всех платформах.
Отказ от ответственности : я являюсь автором этой библиотеки.
источник
Эффективный тип, лежащий в основе size_t, зависит от реализации . Стандарт C определяет его как тип, возвращаемый оператором sizeof; Помимо беззнакового и своего рода интегрального типа, size_t может быть практически любым, размер которого может вместить наибольшее значение, которое, как ожидается, будет возвращено функцией sizeof ().
Следовательно, строка формата, которая будет использоваться для size_t, может различаться в зависимости от сервера. На нем всегда должна быть буква «u», но это может быть l или d или что-то еще ...
Уловкой может быть приведение его к самому большому целочисленному типу на машине, гарантируя отсутствие потерь при преобразовании, а затем использование строки формата, связанной с этим известным типом.
источник
size_t
s в самый большой интегральный тип на машине и использовать строку формата, связанную с этим типом. Мой вопрос: есть ли способ сделать это, сохранив чистый код (предупреждения только для допустимых ошибок строки формата printf, без уродливых приведений и т. Д.)? Я мог бы написать оболочку, которая изменяет строку формата, но тогда GCC не сможет выдавать мне предупреждения, когда я законно испортил строку формата.Позже в коде:
my::printf("test ", 1, '\t', 2.0);
источник