Drukowanie znaków szesnastkowych w języku C
Próbuję odczytać wiersz znaków, a następnie wydrukować szesnastkowy odpowiednik znaków.
Na przykład, jeśli mam ciąg znaków "0xc0 0xc0 abc123"
, gdzie pierwsze 2 znaki to c0
w hex, a pozostałe znaki to abc123
W ASCII, to powinienem uzyskać
c0 c0 61 62 63 31 32 33
Jednak printf
użycie %x
daje mi
ffffffc0 ffffffc0 61 62 63 31 32 33
Jak uzyskać żądane wyjście bez "ffffff"
? I dlaczego tylko c0 (i 80) mA ffffff
, ale nie pozostałe znaki?
7 answers
Widzisz ffffff
ponieważ {[3] } jest podpisany w Twoim systemie. W C Funkcje vararg takie jak printf
będą promować wszystkie liczby całkowite mniejsze od int
do int
. Ponieważ char
jest liczbą całkowitą (w Twoim przypadku 8-bitowa signed integer), twoje znaki są promowane do int
poprzez rozszerzenie sign.
Ponieważ c0
i 80
mają wiodący 1-bit (i są ujemne jako 8-bitowa liczba całkowita), są rozszerzane znakiem, podczas gdy inne w próbce nie.
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
Oto rozwiązanie:
char ch = 0xC0;
printf("%x", ch & 0xff);
To zamaskuje górne bity i zachowa tylko dolne 8 bitów, które chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-09 04:52:45
W rzeczy samej, istnieje konwersja typu na int. Możesz również wymusić typ do znakowania za pomocą specyfikacji %hhx.
printf("%hhX", a);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-09 04:13:51
Możesz utworzyć znak unsigned:
unsigned char c = 0xc5;
Wydrukowanie go da C5
, a nie ffffffc5
.
Tylko znaki większe niż 127 są drukowane z ffffff
, ponieważ są ujemne (znak jest podpisany).
Lub możesz rzucić char
podczas drukowania:
char c = 0xc5;
printf("%x", (unsigned char)c);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 08:43:35
Możesz użyć hh
, aby powiedzieć printf
że argument jest znakiem niepodpisanym. Użyj 0
, aby uzyskać zero wypełnienia i 2
, Aby ustawić szerokość na 2. x
lub X
dla małych / dużych znaków szesnastkowych.
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
Edit: jeśli czytelnicy są zaniepokojeni twierdzeniem 2501, że jest to jakoś nie "poprawny" format to proponuję przeczytać printf
link Jeszcze raz. Konkretnie:
Mimo że %c oczekuje argumentu int, można bezpiecznie przekazać znak z powodu promocji liczby całkowitej, która ma miejsce, gdy wywołana jest zmienna funkcja.
Poprawne specyfikacje konwersji dla typów znaków o stałej szerokości (int8_t, etc) są zdefiniowane w nagłówku
<cinttypes>
(C++) lub<inttypes.h>
(C) (chociaż PRIdMAX, PRIuMAX, etc jest synonimem %jd, % ju, etc) .
Jeśli chodzi o jego punkt o signed vs unsigned, w tym przypadku nie ma to znaczenia, ponieważ wartości muszą być zawsze pozytywne i łatwo zmieścić się w podpisanym int. Nie ma podpisanego formatu hexideximal i tak.
Edit 2 : (edycja" kiedy-przyznac-ze-sie-mylisz"):
Jeśli przeczytasz rzeczywisty standard C11 na stronie 311 (329 PDF) znajdziesz:
Hh: Określa, że następujące
d
,i
,o
,u
,x
, lubX
specyfikator konwersji stosuje się do argumentusigned char
lubunsigned char
(argument będzie promowany zgodnie z promocjami całkowitymi, ale jego wartość będzie konwertowane dosigned char
lubunsigned char
przed wydrukowaniem); lub że następujący specyfikator konwersjin
stosuje się do wskaźnika do argumentusigned char
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-13 07:20:32
Prawdopodobnie przechowujesz wartość 0xc0 w zmiennej char
, co prawdopodobnie jest typem podpisanym, a twoja wartość jest ujemna (najbardziej znaczący zestaw bitów). Następnie, podczas drukowania, jest on konwertowany na int
i aby zachować równoważność semantyczną, kompilator wstawia dodatkowe bajty za pomocą 0xff, więc ujemny int
będzie miał taką samą wartość liczbową jak Twój ujemny char
. Aby to naprawić, po prostu wrzuć do unsigned char
podczas drukowania:
printf("%x", (unsigned char)variable);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-12 17:05:13
Prawdopodobnie drukujesz z podpisanej tablicy znaków. Albo wypisuje z tablicy znaków niepodpisanych, albo zamaskuje wartość za pomocą 0xff: np. ar[i] & 0xFF. Wartości c0 są rozszerzane, ponieważ ustawiony jest Bit wysoki (znak).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-09 04:03:31
Spróbuj czegoś takiego:
int main()
{
printf("%x %x %x %x %x %x %x %x\n",
0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}
Co daje:
$ ./foo
c0 c0 61 62 63 31 32 33
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-15 17:43:07