[c] C에서 16 진수 문자 인쇄

한 줄의 문자를 읽은 다음 해당 문자에 해당하는 16 진수를 인쇄하려고합니다.

예를 들어, "0xc0 0xc0 abc123"처음 두 문자가 c016 진수이고 나머지 문자가 abc123ASCII 인 문자열이 있는 경우 다음을 얻어야합니다.

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보다는 모든 정수가 작은 촉진 intint. 이후 char정수 (귀하의 경우 8 비트 부호있는 정수)입니다, 당신의 문자가 승진되는 int부호 확장을 통해.

이후 c080선도적 인 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제로 패딩을 얻을 수 및 22로 폭을 설정 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