Оператор Тильды в C

 unsigned short int i = 0;
 printf("%u\n",~i);

Почему этот код возвращает 32-битное число в консоли? Он должен быть 16 бит, так как короткий - 2 байта.

Выход составляет 4 294 967 295, и он должен быть 65 535.

+4
источник поделиться
4 ответа

%u ожидает unsigned int; если вы хотите напечатать unsigned short int, используйте %hu.

ИЗМЕНИТЬ

Лундин прав, что ~i будет преобразован в тип int перед передачей printf. i также преобразуется в int за счет перехода к вариационной функции. Тем не менее, printf преобразует аргумент обратно в unsigned short перед печатью, если используется спецификатор преобразования %hu:

7.21.6.1 Функция fprintf
...
3 Формат должен быть многобайтовой последовательностью символов, начиная и заканчивая ее начальным состояние сдвига. Формат состоит из нуля или более директив: обычный многобайтовый символы (не %), которые не изменяются в выходной поток; и преобразование спецификации, каждый из которых приводит к получению нулевых или более последующих аргументов, преобразование их, если это применимо, в соответствии с соответствующим спецификатором преобразования и затем записывая результат в выходной поток.
...
7 Модификаторы длины и их значения:
...
h Указывает, что для спецификатора преобразования d, i, o, u, x или x применяется short int или unsigned short int ( аргумент будет были повышены в соответствии с целыми рекламными акциями, но его стоимость должна преобразуется в short int или unsigned short int перед печатью); или что следующий указатель преобразования n применяется к указателю на аргумент short int.

Акцент мой.

Таким образом, поведение не undefined; это будет только undefined, если либо i, либо ~i не являются целыми типами.

+5
источник

Когда вы передаете аргумент printf, и этот аргумент имеет целочисленный тип короче int, он неявно продвигается до int в соответствии с правилами продвижения аргументов K & R. Таким образом, ваш printf -call действительно ведет себя так:

printf("%u\n", (int)~i);

Обратите внимание, что это поведение undefined, так как вы сказали printf, что аргумент имеет тип unsigned, тогда как int фактически является подписанным типом. Преобразуйте i в unsigned short, а затем в unsigned, чтобы решить поведение undefined и вашу проблему:

printf("%u\n", (unsigned)(unsigned short)~i);
+4
источник

N1570 6.5.3.3 Унарные арифметические операторы p4:

Результат оператора ~ является поразрядным дополнением его (продвинутого) операнда (то есть, каждый бит в результате устанавливается тогда и только тогда, когда соответствующий бит в преобразованном операнде не задано). Целые рекламные акции выполняются в операнде, и результат имеет продвинутого типа....

Integer тип, меньший, чем int, увеличивается до int. Если sizeof(unsigned short) == 2 и sizeof(int) == 4, то итоговый тип int.

И что еще, printf спецификатор преобразования %u ожидает unsigned int, поэтому представление int интерпретируется как unsigned int. Вы в основном лжете компилятору, и это поведение undefined.

+4
источник

Это потому, что аргументы printf() помещаются в стек в словах, так как внутри printf нет способа узнать, что аргумент короткий. Кроме того, используя формат %u, вы просто заявляете, что передаете беззнаковый номер.

+3
источник

Посмотрите другие вопросы по меткам или Задайте вопрос