Warum verhält sich das Komplement durch printf anders?

Warum verhält sich das Komplement durch printf anders?


Ich las ein Kapitel über bitweise Operatoren, stieß auf das 1er-Komplement-Operatorprogramm und beschloss, es auf Visual C++ auszuführen.


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

Es gibt die gültige Ausgabe:251


Dann verwenden Sie statt d als Variable, um den Wert von ~c zu halten , habe ich mich entschieden, den Wert von ~c direkt zu drucken .


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

Es gibt die Ausgabe -5 .


Warum hat es nicht funktioniert?


Antworten:


In dieser Anweisung:


printf("%d",~c);

die c wird in int umgewandelt 1 geben Sie vor ein ~ (bitweises Komplement) wird angewendet. Dies liegt an ganzzahligen Werbeaktionen , die als Operand von ~ aufgerufen werden . In diesem Fall ein Objekt von unsigned char Typ wird zu (signiert) int heraufgestuft , was dann (nach ~ Operatorauswertung), die von printf verwendet wird Funktion, mit passendem %d Formatbezeichner.


Beachten Sie, dass Standardargument-Promotions (als printf ist eine variadische Funktion) spielt hier keine Rolle, da das Objekt bereits vom Typ int ist .


Andererseits in diesem Code:


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

die folgenden Schritte erfolgen:



  • c unterliegt ganzzahligen Beförderungen wegen ~ (auf die gleiche Weise wie oben beschrieben)

  • ~c rvalue wird als (signed) int ausgewertet Wert (z. B. -5 )

  • d=~c führt eine implizite Konvertierung von int durch bis unsigned char , als d hat einen solchen Typ. Sie können es sich ähnlich vorstellen wie d = (unsigned char) ~c . Beachten Sie, dass d darf nicht negativ sein (dies ist die allgemeine Regel für alle vorzeichenlosen Typen).

  • printf("%d", d); ruft Standardargument-Promotions auf , also d wird in int umgewandelt und der (nicht negative) Wert bleibt erhalten (d.h. der int Typ kann alle Werte von unsigned char darstellen Typ).



1) unter der Annahme, dass int kann alle Werte von unsigned char darstellen (siehe Kommentar von T.C. unten), aber es ist sehr wahrscheinlich auf diese Weise passieren. Genauer gesagt nehmen wir an, dass INT_MAX >= UCHAR_MAX hält. Typischerweise der sizeof(int) > sizeof(unsigned char) Holds und Byte bestehen aus acht Bits. Sonst die c würde in unsigned int konvertiert werden (wie in C11 Unterabschnitt §6.3.1.1/p2), und der Formatbezeichner sollte auch entsprechend in %u geändert werden um ein UB zu vermeiden (C11 §7.21.6.1/p9).