Вывод bool в printf

Есть переменная:

bool x = true;

Хочу её загнать в printf в виде числа. Очевидно, что можно сделать

printf("%d", (int)x);

но кастить тип как-то лень и хочется сделать что-то такое:

printf("%hhu", x);

Это тоже работает поскольку с unsigned char и bool занимают по 1 байту, но разрешает ли стандарт такой вывод?


Ответы (1 шт):

Автор решения: wololo

Неизвестные аргументы, передаваемые в вариативную функцию подвергаются расширению аргументов по-умолчанию (default argument promotions). Суть его в следующем:

  • типы с плавающей точкой подвергаются расширению типов с плавающей точкой (floating-point promotion),
  • Целочисленные типы и типы перечисления подвергаются целочисленному расширению (integral promotions)

expr.call/12:

[...] If the argument has integral or enumeration type that is subject to the integral promotions, or a floating-point type that is subject to the floating-point promotion, the value of the argument is converted to the promoted type before the call. These promotions are referred to as the default argument promotions.

При расширении типов с плавающей точкой значение типа float преобразуется к значению типа double. conv.fpprom/1:

A prvalue of type float can be converted to a prvalue of type double. The value is unchanged.

Описание процесса целочисленного расширения довольно объёмно, см.: conv.prom.
Но что касается типа bool, то он при целочисленном расширении преобразуется к типу int, причём значение false преобразуется в 0, а значение true преобразуется в 1. conv.prom/6:

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

Таким образом, значение типа bool, передаваемое в функцию std::printf, перед вызовом преобразуется в значение типа int. А значит его можно вывести так:

bool x = true;
printf("%d", x);

Разберём печать bool с помощью %hhu
Спецификатор преобразования %hhu говорит, что функция printf ожидает получить значение типа unsigned int, которое она перед выводом преобразует в значение типа unsigned char. Так как тип фактически передаваемого аргумента не соответствует спецификатору преобразования (bool расширяется до int)

bool x = true;
printf("%hhu", x);

то поведение программы не определено.

N1570, 7.21.6.1/9:

[...] If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.


P.S.

Стандарт языка не гарантирует, что тип bool занимает один байт. expr.sizeof/1:

[Note 1: In particular, the values of sizeof(bool), sizeof(char16_­t), sizeof(char32_­t), and sizeof(wchar_­t) are implementation-defined.65 — end note]

  1. sizeof(bool) is not required to be 1.
→ Ссылка