оператор дополнения единиц с коротким int

#include <stdio.h>
#include <string.h>

main()
{
short int x=0x55AA;
printf("%x ",~x);
}

Вышеприведенная программа выводит: ffffaa55. Я ожидал o/p только aa55, так как короткий int составляет 2 байта. Кто-нибудь может объяснить это?


person debonair    schedule 30.08.2014    source источник
comment
@pat о, я думал, что OP спросил, почему ~x и -x дали разные результаты. Я не понял вопроса - мой плохой.   -  person Benjamin Gruenbaum    schedule 30.08.2014
comment
@Benjamin Gruenbaum ~x является дополнением к x..   -  person chux - Reinstate Monica    schedule 31.08.2014


Ответы (4)


У тебя есть:

short int x = 0x55AA;
~x;

Выражение ~x имеет тип int.

person Bill Lynch    schedule 30.08.2014
comment
... Кроме того, %x в любом случае является спецификатором формата int. - person Clifford; 30.08.2014
comment
@Clifford: Точнее, узкий вариативный аргумент будет повышен до int независимо от того, какой спецификатор формата используется. (И %x на самом деле является спецификатором формата unsigned int) - person AnT; 30.08.2014
comment
@AndreyT: Точно ;-) - person Clifford; 30.08.2014
comment
если каждый тип данных нужно преобразовать в int, то как насчет char x=0X55AA; printf(%x,~x); ? - person debonair; 30.08.2014
comment
Это немного сложнее, потому что выбор реализации зависит от того, является ли char подписанным или неподписанным. Итак, в зависимости от вашей реализации, ~x повышается до signed int или unsigned int. - person Bill Lynch; 30.08.2014
comment
@sharth Вопрос char ... повышается до signed int или unsigned int. Если int может представлять все значения исходного типа (ограниченные шириной для битового поля), значение преобразуется в int; в противном случае он преобразуется в беззнаковое целое число. Это называется целочисленным продвижением C11dr §6.3.1.1 2. Это означает, что 8-битные char, signed/unsigned или ни одно из них не будет повышено до int, а не unsigned. - person chux - Reinstate Monica; 31.08.2014
comment
@sharth: если char уже, чем int, char всегда повышается до подписанного int, независимо от того, является ли само char подписанным или беззнаковым. - person AnT; 31.08.2014

Язык C никогда не выполняет вычисления в типах уже, чем [signed/unsigned] int. Каждый раз, когда вы используете значение более узкого типа (например, short или char) в выражении, это значение неявно повышается до [signed/unsigned] int. Одна важная деталь здесь заключается в том, что даже если исходный узкий тип — unsigned, он все равно будет повышен до знакового типа int (при условии, что он вписывается в диапазон int). Это то, что следует иметь в виду в подобных случаях.

Обратите внимание, что не только выражение ~x имеет тип int, но и само x повышается до int еще до того, как ~ сможет что-то сделать. Другими словами, ваш ~x интерпретируется как ~(int) x.

Если вам нужен результат исходного узкого типа, вы должны явно преобразовать его обратно в исходный тип. В случае printf, где явное преобразование ничего не решит (поскольку аргумент с переменным числом аргументов все равно будет преобразован в int), вы можете использовать спецификаторы формата printf, чтобы интерпретировать соответствующий аргумент как значение более узкого типа.

В качестве примечания, спецификатор формата %x ожидает аргумент типа unsigned int. Вместо этого передача отрицательного значения int не допускается.

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

person AnT    schedule 30.08.2014
comment
Даже если вы вернете ~x обратно в short int, оно снова будет повышено до int при передаче в printf. В этот момент он, вероятно, будет дополнен знаком (поскольку старший бит теперь установлен). Чтобы получить желаемое поведение, его следует привести к unsigned short или использовать правильный спецификатор формата. - person pat; 30.08.2014
comment
если каждый тип данных нужно преобразовать в int, то как насчет char x=0X55AA; printf(%x,~x); ? - person debonair; 30.08.2014
comment
@debonair: А как насчет этого? Как я уже говорил выше, в ~x значения типа char точно так же преобразуются в int. Единственная проблема в том, что 0x55AA не влезет в типичный char. - person AnT; 30.08.2014

main()
{
 short int x=0x55AA;
 printf("%x ",~x);
}

Здесь ~ x рассматривается как подписанный int. Если вы хотите, чтобы o/p был aa55, вам следует выполнить приведение типов к unsigned short in.so, попробуйте так.

 main()
 {
   short int x=0x55AA;
   printf("%x ",(unsigned short int)~x);//typecasting
 }
person Anbu.Sankar    schedule 30.08.2014

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

Более того, "%x" в любом случае является спецификатором формата int без знака.

Существуют различные решения, например:

short x = 0x55AA ;
short nx = ~x ;
printf("%x ",~nx) ;


short x = 0x55AA ;
printf("%x ",~x & 0x0000FFFF ) ;
person Clifford    schedule 30.08.2014