Perché il complemento si comporta in modo diverso tramite printf?

Perché il complemento si comporta in modo diverso tramite printf?


Stavo leggendo un capitolo sugli operatori bit per bit, mi sono imbattuto nel programma dell'operatore del complemento 1 e ho deciso di eseguirlo su Visual C++.


int main ()
{
unsigned char c = 4, d;
d = ~c;
printf("%d\n", d);
}

Fornisce l'output valido:251


Quindi invece di usare d come variabile per contenere il valore di ~c , ho deciso di stampare direttamente il valore di ~c .


int main ()
{
unsigned char c=4;
printf("%d\n", ~c);
}

Fornisce l'output -5 .


Perché non ha funzionato?


Risposte:


In questa dichiarazione:


printf("%d",~c);

il c viene convertito in int 1 digita prima ~ (complemento bit per bit) viene applicato l'operatore. Ciò è dovuto a promozioni intere , che vengono richiamati all'operando di ~ . In questo caso un oggetto di unsigned char il tipo è promosso a (firmato) int , che è quindi (dopo ~ valutazione operatore) utilizzato da printf funzione, con %d corrispondente identificatore di formato.


Nota che promozioni di argomenti predefiniti (come printf è una funzione variadica) non gioca alcun ruolo qui, poiché l'oggetto è già di tipo int .


D'altra parte, in questo codice:


unsigned char c = 4, d;
d = ~c;
printf("%d", d);

si verificano i seguenti passaggi:



  • c è soggetto a promozioni intere a causa di ~ (allo stesso modo, come sopra descritto)

  • ~c rvalue viene valutato come (firmato) int valore (ad es. -5 )

  • d=~c effettua una conversione implicita da int a unsigned char , come d ha tale tipo. Potresti pensare che sia lo stesso di d = (unsigned char) ~c . Nota che d non può essere negativo (questa è la regola generale per tutti i tipi senza segno).

  • printf("%d", d); invoca promozioni di argomenti predefiniti , quindi d viene convertito in int e il valore (non negativo) viene mantenuto (cioè il int type può rappresentare tutti i valori di unsigned char tipo).



1) assumendo che int può rappresentare tutti i valori di unsigned char (vedi il commento di TC sotto), ma è molto probabile che avvenga in questo modo. Più specificamente, assumiamo che INT_MAX >= UCHAR_MAX tiene. Tipicamente il sizeof(int) > sizeof(unsigned char) hold e byte sono costituiti da otto bit. Altrimenti il ​​c verrebbe convertito in unsigned int (come da sottoclausola C11 §6.3.1.1/p2), e anche l'identificatore di formato dovrebbe essere modificato di conseguenza a %u per evitare di ottenere un UB (C11 §7.21.6.1/p9).