Ich versuche, eine Zeichenzeile einzulesen und dann das hexadezimale Äquivalent der Zeichen auszudrucken.
Wenn ich zum Beispiel eine Zeichenfolge habe "0xc0 0xc0 abc123"
, bei der die ersten beiden Zeichen c0
hexadezimal und die restlichen Zeichen abc123
in ASCII sind, sollte ich sie erhalten
c0 c0 61 62 63 31 32 33
Die printf
Verwendung %x
gibt mir jedoch
ffffffc0 ffffffc0 61 62 63 31 32 33
Wie bekomme ich die gewünschte Ausgabe ohne die "ffffff"
? Und warum hat nur c0 (und 80) die ffffff
, aber nicht die anderen Zeichen?
"\xc0\xc0abc123"
Antworten:
Sie sehen das,
ffffff
weilchar
auf Ihrem System signiert ist. In C werden mit vararg-Funktionenprintf
alle Ganzzahlen heraufgestuft , die kleiner alsint
bis sindint
. Dachar
es sich um eine Ganzzahl handelt (in Ihrem Fall eine 8-Bit-Ganzzahl mit Vorzeichen), werden Ihre Zeichenint
über die Vorzeichenerweiterung heraufgestuft.Da
c0
und80
ein führendes 1-Bit haben (und als 8-Bit-Ganzzahl negativ sind), werden sie vorzeichenerweitert, während die anderen in Ihrem Beispiel dies nicht tun.Hier ist eine Lösung:
Dadurch werden die oberen Bits ausgeblendet und nur die unteren 8 Bits beibehalten, die Sie möchten.
quelle
unsigned char
ist eine Anweisung kleiner in gcc4.6 für x86-64 ...x
einen vorzeichenlosen Typ erfordert, ch jedoch zu int heraufgestuft wird. Der richtige Code würde einfach ch in unsigned umwandeln oder eine Umwandlung in unsigned char und den Bezeichner verwenden :hhx
.printf("%x", 0)
, wird nichts gedruckt.printf("%.2x", 0);
, die minimalen Zeichen auf 2 zu erhöhen. Um ein Maximum festzulegen, stellen Sie das vor. mit einer Nummer. Zum Beispiel können Sie nur 2 Zeichen erzwingen, indem Sie tunprintf("%2.2x", 0);
printf("%x", ch & 0xff)
es besser sein sollte, als nurprintf("%02hhX", a)
die Antwort von @ brutal_lobster zu verwenden ?In der Tat gibt es eine Typkonvertierung in int. Sie können den Typ auch erzwingen, indem Sie den% hhx-Bezeichner verwenden.
In den meisten Fällen möchten Sie auch die Mindestlänge festlegen, um das zweite Zeichen mit Nullen zu füllen:
ISO / IEC 9899: 201x sagt:
quelle
Sie können ein vorzeichenloses Zeichen erstellen:
Drucken wird es geben
C5
und nichtffffffc5
.Nur die Zeichen, die größer als 127 sind, werden mit dem Zeichen gedruckt,
ffffff
da sie negativ sind ( Zeichen ist signiert).Oder Sie können das
char
beim Drucken gießen :quelle
Sie speichern wahrscheinlich den Wert 0xc0 in einer
char
Variablen, was wahrscheinlich ein vorzeichenbehafteter Typ ist, und Ihr Wert ist negativ (höchstwertiges Bit gesetzt). Beim Drucken wird es dann in konvertiertint
, und um die semantische Äquivalenz beizubehalten, füllt der Compiler die zusätzlichen Bytes mit 0xff auf, sodass das Negativint
den gleichen numerischen Wert wie Ihr Negativ hatchar
. Um dies zu beheben, werfen Sieunsigned char
beim Drucken einfach auf :quelle
Sie können
hh
damit feststellen,printf
dass das Argument ein vorzeichenloses Zeichen ist. Verwenden Sie0
diese Option, um einen Nullpunkt zu erhalten und2
die Breite auf 2x
oderX
für Hex-Zeichen in Klein- / Großbuchstaben festzulegen.Bearbeiten : Wenn die Leser über die Behauptung von 2501 besorgt sind, dass dies irgendwie nicht die "richtigen" Formatspezifizierer sind, schlage ich vor, dass sie den
printf
Link erneut lesen . Speziell:In diesem Fall spielt es keine Rolle, ob die Werte signiert oder nicht signiert sind, da die Werte immer positiv sein müssen und leicht in ein signiertes Int passen. Es gibt sowieso keinen vorzeichenbehafteten hexideximalen Formatbezeichner.
Edit 2 : (Ausgabe "Wann muss man zugeben, dass man falsch liegt?"):
Wenn Sie den aktuellen C11-Standard auf Seite 311 (329 des PDF) lesen , finden Sie:
quelle
inttypes.h
char
undunsigned char
werden befördert zuint
) [ en.cppreference.com/w/cpp/language/variadic_arguments] . Sie müssten die PRI-Spezifizierer nur für Dinge verwenden, die nicht in Ihre Plattform passenint
- zunsigned int
.%x
ist korrekt für unsigned int not int. Die Typen char und unsigned char werden zu int heraufgestuft. Darüber hinaus gibt es keine Garantie dafür, dass uint8_t als vorzeichenloses Zeichen definiert ist.Sie drucken wahrscheinlich von einem signierten char-Array. Entweder aus einem vorzeichenlosen Zeichenarray drucken oder den Wert mit 0xff maskieren: zB ar [i] & 0xFF. Die c0-Werte werden vorzeichenerweitert, da das hohe (Vorzeichen-) Bit gesetzt ist.
quelle
Versuchen Sie so etwas:
Welches produziert dies:
quelle