Forum: PC-Programmierung warum wird char mit 4 Bytes dargestellt?


von Walter K. (walter_k488)


Lesenswert?

#include <stdio.h>

int main(){
  signed char test = 'a';
  signed char neg_test = ~'a';

  printf("test = %d Byte \n", sizeof(test) );
  printf("Integer: %d\n", test );
  printf("ist in Hex: x%x\n", test);
  printf( "neg_test = %d Byte(s) \n", sizeof(neg_test) );
  printf("Integer: %d\n", neg_test );
  printf("ist in Hex: x%x\n", neg_test);
  return 0; }

Ausgabe:
test = 1 Byte
Integer: 97
ist in Hex: x61
neg_test = 1 Byte(s)
Integer: -98
ist in Hex: xffffff9e

Meine Frage bezieht sich auf die letzte Zeile der Ausgabe

: Bearbeitet durch User
von DanielF (Gast)


Lesenswert?

Führende Nullen werden weggelassen und bei HEX-Darstellung wird kein 
Minus angezeigt. Die Fs bzw. Einsen müssen also irgendwie ausgegeben 
werden.


Lieber immer die Breite mitangeben, z.B.: "0X%02X", "0X%04X"

Gruß
Daniel

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Walter K. schrieb:
> printf("test = %d Byte \n", sizeof(test) );

Das ist übrigens immer 1, denn sizeof gibt die Größe in Vielfachen von 
"char" an, und "test" ist vom Typ "char", und char ist nunmal genau 1 
char groß.

von Walter K. (walter_k488)


Lesenswert?

DanielF schrieb:
> Die Fs bzw. Einsen müssen also irgendwie ausgegeben
> werden.

das heisst aber auch, dass char 4 Bytes gross ist - und nicht 1 Byte, 
wie es für -128 bis +127 notwendig wäre?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Walter K. schrieb:
> das heisst aber auch, dass char 4 Bytes gross ist

Nein, char und short werden bei der Übergabe an "printf" auf "int" 
erweitert. Bei Computern mit 2er-Komplement wird das Vorzeichenbit dabei 
auf die neuen 24 bzw. 16 bits kopiert.
In C und C++ ist "char" per Definition immer genau 1 Byte groß; 1 Byte 
hat mindestens 8 bit.

von Route_66 H. (route_66)


Lesenswert?

Walter K. schrieb:
> das heisst aber auch, dass char 4 Bytes gross ist - und nicht 1 Byte,
> wie es für -128 bis +127 notwendig wäre?

Nein. Dein printf fügt ohne Formatierungsangaben die 3 0xFF hinzu.

von Walter K. (walter_k488)


Lesenswert?

Route 6. schrieb:
> Nein. Dein printf fügt ohne Formatierungsangaben die 3 0xFF hinzu.

Ah - alles klar .. Danke

von devzero (Gast)


Lesenswert?

printf("%hhx", dein_char);

von Yalu X. (yalu) (Moderator)


Lesenswert?

devzero schrieb:
> printf("%hhx", dein_char);

Zu spät, aber dafür etwas ausführlicher:

Walter K. schrieb:
> DanielF schrieb:
>> Die Fs bzw. Einsen müssen also irgendwie ausgegeben
>> werden.
>
> das heisst aber auch, dass char 4 Bytes gross ist - und nicht 1 Byte,
> wie es für -128 bis +127 notwendig wäre?

Nein, aber das "%x"-Format stellt den Wert als int dar. Für short gibt
es dan Formatpräfix "h" und für char "hh". Das Format, das du sucht,
ist also "%hhx" oder "%#hhx". Letzteres stellt automatisch ein "0x" vor
die ausgegebene Zahl.

"%d" sollte auch nicht für sizeof-Ergebnisse verwendet werden, das diese
nicht vom Typ int sondern size_t sind. Das richtige Format ist hier
"%zd".

von Walter K. (walter_k488)


Lesenswert?

Niklas G. schrieb:
>> printf("test = %d Byte \n", sizeof(test) );
>
> Das ist übrigens immer 1, denn sizeof gibt die Größe in Vielfachen von
> "char" an, und "test" ist vom Typ "char", und char ist nunmal genau 1
> char groß.

hmm .. dann haette ich aber auch für den Typ size_t des Rückgabewerte 
von sizeof() in printf auch %z als Formatbezeichner nutzen müssen ...

edit: .. da war jemand schneller ;-)

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Zudem werden bei Funktionen mit variabler Argumentenliste (wie printf) 
die Werte auf mindestens int (bei Ganzzahltypen) oder double (bei 
Fließkommatypen) aufgewertet.

D.h bei
1
  signed char neg_test = ~'a';
2
  printf("ist in Hex: x%x\n", neg_test);
 wird tatsächlich ein int übergeben.
Bei %hhx auch, aber da wird halt nur ein Byte berücksichtigt.

!ACHTUNG
Bei scanf werden im allgemeinen Pointer/Adressen übergeben.
da ist es extrem wichtig, den richtigen Formatspecifier zu wählen.
Sonst werden mal 4 Byte geschrieben, wo nur 1 BYte Platz ist.

von zitter_ned_aso (Gast)


Lesenswert?

Dirk B. schrieb:
> Zudem werden bei Funktionen mit variabler Argumentenliste (wie printf)
> die Werte auf mindestens int (bei Ganzzahltypen) oder double (bei
> Fließkommatypen) aufgewertet.

aber man hatte schon bei der Zuweisung mit 4 Bytes zu tun oder?

also hier:

Walter K. schrieb:
> signed char neg_test = ~'a';

1
  size_t len = sizeof('a');
2
  printf("%zu\n", len);

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Yalu X. schrieb:
> Das richtige Format ist hier
> "%zd".

Eher %zu, denn size_t ist ja unsigned.

zitter_ned_aso schrieb:
> aber man hatte schon bei der Zuweisung mit 4 Bytes zu tun oder?
Ja, char-Literale wie 'a' sind in C vom Typ "int". Der wird dann aber 
auf "char" gekürzt.

In C++ ist das aber nicht so - da ist 'a' vom Typ char.

Daher liefert das

zitter_ned_aso schrieb:
> size_t len = sizeof('a');
>   printf("%zu\n", len);

in C z.B. 4 (je nach Plattform), in C++ immer 1. Das ist einer der 
wenigen Fälle wo C-Code in C++ anders ausgeführt wird.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Niklas G. schrieb:
> Yalu X. schrieb:
>> Das richtige Format ist hier
>> "%zd".
>
> Eher %zu, denn size_t ist ja unsigned.

Ja, danke für die Richtigstellung. Ich hatte mich so sehr auf das z
eingeschossen, dass ich den Fehler mit dem d ganz übersehen habe :)

von Dirk B. (dirkb2)


Lesenswert?

zitter_ned_aso schrieb:
> aber man hatte schon bei der Zuweisung mit 4 Bytes zu tun oder?

Jein.

Die Berechnung von ~ wird als int ausgeführt.
'a' ist auch ein int

In neg_test passt aber nur ein Byte.

von Walter K. (walter_k488)


Lesenswert?

o.k. - also Formatbezeichner in printf beim type size_t ist %zu (ab C99 
- und vorher bei C90 war es wohl %lu )

von Dirk B. (dirkb2)


Lesenswert?

Walter K. schrieb:
> o.k. - also Formatbezeichner in printf beim type size_t ist %zu

Es geht auch %zo, %zx oder %zX (also alee unsigned Typen)

Das z ist der length modifier und das u (o,x,X) der conversion modifier.

von Rolf M. (rmagnus)


Lesenswert?

Walter K. schrieb:
> und vorher bei C90 war es wohl %lu

Nein, das l steht für long, nicht für size_t. Die müssen nicht zwingend 
beide gleich groß sein. Man kann aber %lu verwenden und den übergebenen 
Parameter nach unsigned long casten.

von Sturm88 (Gast)


Lesenswert?

Rolf M. schrieb:
> Walter K. schrieb:
> und vorher bei C90 war es wohl %lu
>
> Nein, das l steht für long, nicht für size_t. Die müssen nicht zwingend
> beide gleich groß sein. Man kann aber %lu verwenden und den übergebenen
> Parameter nach unsigned long casten.

%z wurde erst mit c99 Standard

Beim c90 musste man wohl sich mit Long behelfen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.