sourcecode

printf의 h와 hh 수식어의 목적은 무엇입니까?

copyscript 2022. 9. 11. 17:28
반응형

printf의 h와 hh 수식어의 목적은 무엇입니까?

이외에는%hn그리고.%hhn(여기서는h또는hh포인트 투 오브젝트의 크기를 지정합니다).h그리고.hh에 대한 수식어printf포맷 지정자를 지정하시겠습니까?

가변 함수에 적용하기 위해 표준에서 요구하는 디폴트 프로모션으로 인해 형식 인수를 전달할 수 없습니다.char또는short(또는 그 서명/지정된 변형) ~printf.

7.19.6.1(7)에 따라h수식자:

다음의 d, i, o, u, x, 또는 X 변환 지정자가 짧은 int 또는 부호 없는 짧은 int 인수에 적용됨을 지정한다(인수는 정수 승진에 따라 승격되지만, 그 값은 인쇄 전에 짧은 int 또는 부호 없는 짧은 int 인수로 변환되어야 한다). 또는 다음의 n 변환 지정자가 s에 포인터에 적용됨을 지정한다.인수가 필요합니다.

인수가 실제로 유형인 경우short또는unsigned short, 그 후 로의 프로모션int뒤이어 로의 개종short또는unsigned short승진과 같은 가치를 가져다 줄 것이다int어떤 변환도 없이 말이죠.따라서 형식 인수의 경우short또는unsigned short,%d,%u, 등에게 동일한 결과를 제공해야 합니다.%hd,%hu등(및 에 대해서도 마찬가지입니다.char종류와hh).

내가 아는 한, 이 상황이 유일하게h또는hh수식어는 인수가 그것을 넘겼을 때 유용할 수 있습니다.int의 범위 밖에short또는unsigned short,예.

printf("%hu", 0x10000);

그러나 이와 같이 잘못된 활자를 전달하면 정의되지 않은 동작이 발생하므로 0이 출력될 것으로 예상할 수 없습니다.

내가 본 실제 사례 중 하나는 다음과 같은 코드이다.

char c = 0xf0;
printf("%hhx", c);

저자가 예상하는 인쇄 장소f0평원이 있는 실장에도 불구하고char서명된 유형(이 경우,printf("%x", c)인쇄하다fffffff0또는 유사).하지만 이 기대가 정당화될까요?

(주의: 원래 타입은char로 승격됩니다.int로 다시 변환되었습니다.unsigned char대신char따라서 출력되는 값이 변경됩니다.그러나 표준이 이 동작을 규정합니까?아니면 고장난 소프트웨어에 의존할 가능성이 있는 구현 세부사항입니까?

한 가지 가능한 이유는 형식화된 입력 함수에서 이러한 수식어를 사용할 때의 대칭성 때문입니다.꼭 그럴 필요는 없겠지만, 그럴 가치가 있는 건 아닐까요?

C99 논거 문서에서 "h"와 "hh" 수식어에 대한 대칭의 중요성은 언급되지 않았지만 위원회는 "%p" 변환 지정자가 왜 지원되는지에 대한 고려사항으로 언급합니다.fscanf()(C99에 대해서는 새로운 것은 아니지만, C90에서는 "%p" 지원이 제공되고 있습니다).

fprintf와의 대칭성을 위해 %p와의 입력 포인터 변환이 C89에 추가되었습니다.

의 항에서fprintf(), C99 이론적 근거 문서는 "hh"가 추가된 것을 설명하지만, 단지 독자에게 "hh"를 언급할 뿐입니다.fscanf()섹션:

%hh 및 %ll 길이 수식자가 C99에 추가되었습니다(제7.19.6.2항 참조).

가느다란 실타래인 건 알지만, 어쨌든 추측하고 있는 중이니까, 어떤 논쟁이라도 해야겠다고 생각했어요.

또한, 완전성을 위해, "h" 수식어는 원래 C89 표준에 있었다. 아마도 수식어를 사용하기 위한 기술적 요건이 없었더라도, 광범위한 기존 사용으로 인해 엄격히 필요하지 않았을 것이다.

또 다른 편리한 곳은 snprintf 사이즈 체크입니다.gcc7은 snprintf를 사용할 때 사이즈 체크가 추가되어 실패하게 됩니다.

char arr[4];
char x='r';
snprintf(arr,sizeof(arr),"%d",r);

따라서 문자를 포맷할 때 %d를 사용할 때 더 큰 문자를 사용해야 합니다.

이 커밋은 문자 배열 크기를 %d에서 %h로 늘리는 대신 이러한 수정 사항을 보여 줍니다.이것에 의해, 보다 정확한 설명이 제공됩니다.

https://github.com/Mellanox/libvma/commit/b5cb1e34a04b40427d195b14763e462a0a705d23#diff-6258d0a11a435aa372068037fe161d24

내가 생각해낼 수 있는 유일한 용도는 바로 '무조건'을 통과시키기 위해서이다.unsigned short또는unsigned char를 사용하여%x변환 지정자.간단히 베어(bare)를 사용할 수 없습니다.%x- 이 값은 다음과 같이 승격될 수 있습니다.int보다는unsigned int동작을 정의하지 않았습니다.

당신의 대안은 주장을 명시적으로 하는 것이다.unsigned; 또는 사용방법%hx/%hhx막론하고

%...x모든 값이 부호 없는 것으로 해석됩니다.따라서 음수는 부호 없는 변환으로 인쇄됩니다.대부분의 프로세서가 사용하는 2의 보완 연산에서는 부호화된 음수와 부호화되지 않은 양의 등가 사이에 비트 패턴에 차이가 없습니다.이는 계수 연산(C99 표준에 따라 필드의 최대값과 음수의 최대값을 더한 값)에 의해 정의됩니다.많은 소프트웨어 - 특히 디버깅코드를 사용할 가능성이 높은 경우%x- 부호 있는 음수 값과 부호 없는 캐스트의 비트 표현이 동일하다는 무언의 가정을 합니다.이것은 2의 보완 머신에서만 해당됩니다.

이 캐스팅의 메커니즘은 서로 다른 정수 표현이 서로 다른 범위를 갖는 가장자리 조건에 도달하지 않는 한, 값의 16진수 표현이 항상 2의 보수로 표현되었음을 암시하는 것일 수 있습니다.이는 값 0이 모든 0의 이진 패턴으로 표현되지 않는 산술 표현에도 해당됩니다.

네거부short로서 표시되다unsigned long따라서 어떤 기계에서도 16진수로 패딩될 것이다.f프로모션의 암묵적인 부호 확장이 원인입니다.printf인쇄합니다.은 동일하지만 필드의 크기에 대해서는 시각적으로 오해의 소지가 있으며, 이는 단순히 존재하지 않는 상당한 범위를 의미합니다.

%hx는 표시된 표현을 잘라내어 실제 사용 사례에서 결론을 내린 그대로 이 패딩을 방지합니다.

동작printf를 통과하면 정의되지 않습니다.int의 범위 밖에short로 인쇄해야 합니다.short그러나 가장 쉬운 구현은 로우 다운캐스트에 의해 높은 비트를 폐기할 뿐이기 때문에 사양상 특정 동작을 필요로 하지 않지만 정상적인 구현은 거의 모두 잘라내기만 합니다.하지만 일반적으로 더 나은 방법이 있습니다.

printf가 값을 채우지 않거나 부호 없는 값의 표현을 표시하지 않는 경우%h별로 쓸모가 없어요.

에 대한 가변 인수printf()기본 변환을 사용하여 자동으로 승격되므로,short또는char값이 로 승격됩니다.int함수에 전달될 때.

이 없는 경우h또는hh올바른 동작을 확실하게 얻으려면 전달된 값을 마스크해야 합니다.수식자를 사용하면 값을 마스킹할 필요가 없어집니다.printf()구현은 작업을 적절하게 수행합니다.

특히 포맷의 경우%hx, 내부 코드printf()다음과 같은 작업을 수행할 수 있습니다.

va_list args;
va_start(args, format);

...

int i = va_arg(args, int);
unsigned short s = (unsigned short)i;
...print s correctly, as 4 hex digits maximum
...even on a machine with 64-bit `int`!

나는 태평하게 추측하고 있다short는 16비트 수량입니다.물론 표준에서는 보증되지 않습니다.

부호 없는 문자를 16진수로 포맷할 때 캐스팅을 피하는 것이 도움이 됩니다.

        sprintf_s(tmpBuf, 3, "%2.2hhx", *(CEKey + i));

간단한 코딩으로 여러 캐스트(IMO)보다 깔끔해 보입니다.

엄밀하게는 필요없다는 것에 동의합니다.따라서 C라이브러리 기능에서는 그 이유만으로는 도움이 되지 않습니다.

다른 깃발들의 대칭성에 대해서는 "좋다"고 할 수 있지만, "전환"을 숨기고 있기 때문에 대부분 역생산적이다.int" 규칙입니다.

언급URL : https://stackoverflow.com/questions/4586962/what-is-the-purpose-of-the-h-and-hh-modifiers-for-printf

반응형