|
Отличие между "%d" и "%zd" в языке C заключается в том, для какого типа данных они предназначены и как обрабатывают потенциальное различие в размере типа int и size_t.
Формат "%d". Назначение: для типа int (знаковое целое, обычно 4 байта).
Возможная проблема: если вы передаёте значение типа size_t (беззнаковое, обычно 8 байт на 64-битных системах) в printf с использованием "%d", то:
- Произойдёт неопределённое поведение (Undefined Behavior, UB), так как тип не соответствует спецификатору. - На 64-битной системе size_t больше int, как следствие printf прочитает только часть байтов, и результат будет некорректным (например, большие числа обрежутся или станут отрицательными).
Формат "%zd" (введён в C99). Назначение: специально для типа size_t (беззнаковый результат `sizeof`, индексы массивов и т.д.).
Преимущество:
- Автоматически подстраивается под реальный размер size_t (4 или 8 байт). - Безопасен и портабелен. - Гарантирует корректный вывод значений size_t без обрезания или неопределённого поведения.
Пример различий:
#include < stdio.h> #include < stddef.h>
int main() { size_t x = 4000000000; // больше 2^31-1 (на 64-битной системе)
printf("%d\n", x); // Ошибка: может вывести отрицательное число или 0 printf("%zd\n", x); // Правильно: 4000000000
return 0;
}
Другие похожие спецификаторы:
"%zu" — для size_t (беззнаковый вывод, z + u). "%td" — для разности указателей (ptrdiff_t, знаковый). "%zd" — знаковый вариант для ssize_t (нестандартный) или для size_t, если вы хотите знаковое представление (редко бывает нужно).
Какой формат когда использовать?
- Всегда используйте "%zd" или "%zu" для вывода значений, связанных с sizeof, strlen, индексами в size_t, длинами контейнеров в безопасном коде. - "%d" — только для обычных чисел int, когда вы точно знаете, что значение помещается в int и не является size_t.
Игнорирование этого различия — частая причина трудноуловимых ошибок при переносе кода между 32-битными и 64-битными платформами.
[Ссылки]
1. Секреты printf. 2. IAR EWB ARM: форматированный вывод printf библиотеки DLIB. 3. Выравнивание в printf по правой стороне выводимого числа. 4. Проблемы с printf и sprintf. | avr-troubleshooting-faq |