Дары муравьям магия

Погрузитесь в мир волшебных подарков для муравейников: магические дары, которые превратят ваш террариум в живую сказку, полную загадок и энергии.

Добро пожаловать в рубрику «Дары муравьям магия» — место‚ где рунические знаки Си превращаются в понятные инструменты. Сегодня мы рассмотрим одну из наиболее запутанных пар спецификаторов форматирования: %zu и %lu. Если вы когда-нибудь видели на экране странное слово «zu» вместо ожидаемого числа‚ эта статья для вас.


Что такое size_t и зачем нужен %zu?

Тип size_t — это беззнаковое целочисленное «что-то»‚ которое используется во всех стандартных функциях библиотеки Си для обозначения размеров и количества байт (например‚ результат sizeof‚ strlen‚ malloc). На 64-битных системах это обычно unsigned long long‚ на 32-битных — unsigned long или даже unsigned int.

Формат %zu появился в стандарте C99 и означает:

  • z — длина для типа size_t;
  • u — беззнаковый десятичный вывод.

Запись гарантирует‚ что программа компилируется и корректно работает на любой платформе‚ вне зависимости от конкретного размера size_t.

А можно просто %lu?

  1. Не портативно: на x64 Windows size_t — unsigned long long‚ откуда при %lu можно получить -1 или неверное число.
  2. Требует замечаний компилятора: GCC и Clang с ключом -Wall -Wextra выводят предупреждение format specifies type ‘unsigned long’ but the argument has type ‘size_t’.
  3. future-proof: Стандарт может поменять размер size_t‚ и ваша программа поломается.

Подводные камни Microsoft Visual Studio

Старые версии MSVC до VS2013 запросто игнорировали %zu‚ поэтому на экране вы видели буквально символы zu.

Хронология поддержки:

Компилятор Мин. версия Пояснение
Microsoft Visual Studio VS2015 (≥ _MSC_VER 1900) Полная поддержка %zu
MSVC < 1900 2010-2013 Частичная/отсутствует; можно использовать %Iu
GCC / Clang (libstdc) C99+ Всегда поддерживается

Как безопасно выводить size_t в устаревшем компиляторе

До VS2015 «муравьи» рекомендуют:

  • Microsoft-only:
    printf("%Iu
    "‚ value);
    — здесь I означает size_t в MSVC.
  • Кроссплатформенно:
    printf("%llu
    "‚ (unsigned long long)value);

    такой каст безопасен‚ но требует явного преобразования.

  • C++ (альтернатива):
    std::cout << value;

    — перегрузка для size_t корректна во всем стандарте С++11+.

Мини-чек-лист для разработчика

  1. Если компилируете в GCC/Clang — смело используйте %zu.
  2. MSVC 2015 и выше: %zu — ваш выбор.
  3. MSVC раньше 2015: используйте %Iu или скажите заказчику обновиться.
  4. Если пишите кроссплатформенную библиотеку — добавьте макро-обёртку:
    
    #ifdef _MSC_VER
    
    #else
    
    #endif
    printf("%" PRI_SIZET‚ my_size);
     

Форматный спецификатор %zu — именно то‚ что вы должны использовать для переменных типа size_t‚ начиная с C99. На современных компиляторах проблем нет‚ а старые можно обмануть макросом или явным приведением. Главное — не игнорировать предупреждения компилятора: они появляются не зря‚ даже если ваш компьютер ведёт себя как муравьиная куча.

Полезные контакты и​ серверы поддержки

  • Электронная почта редакции:
    📧 codespells@mu2race.net
  • Error-catch GitHub-бот для MSVC:
    https://github.com/microsoft/vcpkg
  • Ru.StackOverflow:
    🔍 Тег visual-c++ на ru.SO
  • Телеграм-чат «С++/Си 64-бит»:
    Приглашение в чат – быстрый ответ опытных муравьёв.