ones допълващ оператор с кратко int

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

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

Горната програма дава резултат: ffffaa55. Очаквах o/p само aa55, тъй като short 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; в противен случай се преобразува в unsigned 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 стойност вместо това не е разрешено.

Освен това винаги е по-добра идея да използвате неподписани типове за всякакви операции със семантика на битово ниво.

person AnT    schedule 30.08.2014
comment
Дори ако прехвърлите ~x обратно към short int, той ще бъде повишен до int отново, когато бъде прехвърлен към printf. В този момент вероятно ще бъде разширен знак (тъй като msb вече е зададен). За да получите желаното поведение, трябва да бъде прехвърлено към 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 се третира като signed int. Ако искате o/p като aa55, тогава трябва да направите typecast към unsigned short in. Така че, опитайте така..

 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