한 줄의 문자를 읽은 다음 해당 문자에 해당하는 16 진수를 인쇄하려고합니다.
예를 들어, "0xc0 0xc0 abc123"
처음 두 문자가 c0
16 진수이고 나머지 문자가 abc123
ASCII 인 문자열이 있는 경우 다음을 얻어야합니다.
c0 c0 61 62 63 31 32 33
그러나 printf
사용 %x
하면
ffffffc0 ffffffc0 61 62 63 31 32 33
없이 원하는 출력을 얻으려면 어떻게합니까 "ffffff"
? 그리고 왜 c0 (및 80)에만는 ffffff
있지만 다른 문자는없는 이유는 무엇입니까?
답변
이 시스템에 서명되어 ffffff
있기 때문에 char
표시됩니다. C에서와 같은 가변 인자의 기능 printf
보다는 모든 정수가 작은 촉진 int
에 int
. 이후 char
정수 (귀하의 경우 8 비트 부호있는 정수)입니다, 당신의 문자가 승진되는 int
부호 확장을 통해.
이후 c0
및 80
선도적 인 1 비트를 (그리고 8 비트 정수로 음) 샘플에서 다른 사람이하지 않는 동안, 그들은 로그인 확장되고있다.
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
해결책은 다음과 같습니다.
char ch = 0xC0;
printf("%x", ch & 0xff);
이렇게하면 상위 비트는 가려지고 원하는 하위 8 비트 만 유지됩니다.
답변
실제로 int 로의 유형 변환이 있습니다. 또한 % hhx 지정자를 사용하여 유형을 char로 강제 지정할 수 있습니다.
printf("%hhX", a);
대부분의 경우 두 번째 문자를 0으로 채우려면 최소 길이도 설정해야합니다.
printf("%02hhX", a);
ISO / IEC 9899 : 201x는 다음과 같이 말합니다.
7 길이 수정 자와 그 의미는 다음과 같습니다. hh 다음 d, i, o, u, x 또는 X 변환 지정자가 부호있는 문자 또는 부호없는 문자 인수에 적용되도록 지정합니다 (인수는 정수 승격에 따라 승격됩니다. 그러나 그 값은 인쇄하기 전에 부호있는 문자 또는 부호없는 문자로 변환되어야합니다. 또는 다음
답변
서명되지 않은 문자를 만들 수 있습니다.
unsigned char c = 0xc5;
이 줄 것이다 인쇄 C5
하지 ffffffc5
.
127보다 큰 문자 만 ffffff
음수이기 때문에 인쇄됩니다 (char는 서명 됨).
또는 char
인쇄 하는 동안 캐스팅 할 수 있습니다 .
char c = 0xc5;
printf("%x", (unsigned char)c);
답변
char
아마도 부호있는 유형 인 변수에 0xc0 값을 저장하고 있으며 값은 음수 (최상위 비트 세트)입니다. 그런 다음 인쇄 할 때로 변환되고 int
의미 적 동등성을 유지하기 위해 컴파일러는 추가 바이트를 0xff로 채 웁니다. 따라서 음수 int
는 음수 와 동일한 숫자 값을 갖습니다 char
. 이 문제를 해결하려면 unsigned char
인쇄 할 때 캐스트하십시오 .
printf("%x", (unsigned char)variable);
답변
인수가 부호없는 문자임을 hh
알리는 데 사용할 수 있습니다 printf
. 사용은 0
제로 패딩을 얻을 수 및 2
2로 폭을 설정 x
또는 X
이하 / 대문자 진수 문자.
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
편집 : 독자가 이것이 ‘올바른’형식 지정자가 아니라는 2501의 주장에 대해 우려한다면 printf
링크를 다시 읽으라고 제안 합니다. 구체적으로 특별히:
% c가 int 인수를 예상하더라도 가변 함수가 호출 될 때 발생하는 정수 승격 때문에 char를 전달하는 것이 안전합니다.
고정 너비 문자 유형 (int8_t 등)에 대한 올바른 변환 사양은 헤더
<cinttypes>
(C ++) 또는<inttypes.h>
(C)에 정의되어 있습니다 (PRIdMAX, PRIuMAX 등은 % jd, % ju 등과 동의어 임) .
부호있는 대 부호없는 것에 대한 그의 요점은이 경우 값이 항상 양수 여야하고 부호있는 정수에 쉽게 맞아야하므로 중요하지 않습니다. 어쨌든 서명 된 16 진수 형식 지정자는 없습니다.
편집 2 : ( “당신이 틀 렸음을 인정할 때”판) :
311 페이지 (PDF 329) 에서 실제 C11 표준 을 읽으면 다음 을 찾을 수 있습니다.
HH : 지정하는 다음가
d
,i
,o
,u
,x
, 또는X
변환 지시자는 적용signed char
또는unsigned char
인수 (인수는 정수 프로모션에 따른 증진 된 것이지만, 그 값으로 변환한다signed char
또는unsigned char
인쇄하기 전에); 또는 다음n
변환 지정자가signed char
인수 에 대한 포인터에 적용됩니다 .
답변
서명 된 문자 배열에서 인쇄하고있을 것입니다. 부호없는 문자 배열에서 인쇄하거나 0xff로 값을 마스크합니다 : 예 : ar [i] & 0xFF. 높은 (부호) 비트가 설정 되었기 때문에 c0 값이 부호 확장됩니다.
답변
다음과 같이 시도하십시오.
int main()
{
printf("%x %x %x %x %x %x %x %x\n",
0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}
다음을 생성합니다.
$ ./foo
c0 c0 61 62 63 31 32 33