mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Walter K. (walter_k488)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: DanielF (Gast)
Datum:

Bewertung
-1 lesenswert
nicht 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

Autor: Niklas G. (erlkoenig) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Walter K. (walter_k488)
Datum:

Bewertung
-1 lesenswert
nicht 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?

Autor: Niklas G. (erlkoenig) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Route 6. (route_66)
Datum:

Bewertung
-2 lesenswert
nicht 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.

Autor: Walter K. (walter_k488)
Datum:

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

Ah - alles klar .. Danke

Autor: devzero (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
printf("%hhx", dein_char);

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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".

Autor: Walter K. (walter_k488)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Dirk B. (dirkb2)
Datum:

Bewertung
1 lesenswert
nicht 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
  signed char neg_test = ~'a';
  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.

Autor: zitter_ned_aso (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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';


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



Autor: Niklas G. (erlkoenig) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Walter K. (walter_k488)
Datum:

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

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sturm88 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.