Printf의 적절한 사용은 0S로 패딩 된 포인터를 표시하기 위해 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1255099

  •  12-09-2019
  •  | 
  •  

문제

C에서는 printf를 사용하여 포인터를 표시하고, 제대로 정렬되도록 0s로 패드하고 싶습니다.

내 생각 에이 작업을 수행하는 올바른 방법은 다음과 같습니다.

printf("%016p", ptr);

이것은 작동하지만이 GCC는 다음과 같은 메시지를 불평합니다.

warning: '0' flag used with ‘%p’ gnu_printf format

나는 그것을 위해 약간 검색했고, 다음 스레드는 같은 주제에 있지만 실제로 해결책을 제공하지는 않습니다.

http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html

그것을 읽고, GCC가 불평하는 이유는 내가 제안한 구문이 C99에서 정의되지 않았기 때문입니다. 그러나 표준 승인 방식으로 같은 일을 할 다른 방법을 찾을 수없는 것 같습니다.

그래서 여기에 두 가지 질문이 있습니다.

  • 이 동작이 C99 표준에 의해 정의되지 않았다는 것을 이해 하는가?
  • 그렇다면이 작업을 수행하는 표준 승인 된 휴대용 방법이 있습니까?
도움이 되었습니까?

해결책

#include <inttypes.h>

#include <stdint.h>

printf("%016" PRIxPTR "\n", (uintptr_t)ptr);

그러나 구현 정의 된 방식으로 포인터를 인쇄하지 않습니다 (말한다. DEAD:BEEF 8086 세그먼트 모드의 경우).

다른 팁

사용:

#include <inttypes.h>

printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);

또는 해당 헤더에서 매크로의 다른 변형을 사용하십시오.

또한 일부 구현에 유의하십시오 printf() 인쇄0x'포인터 앞에서; 다른 것들은 그렇지 않습니다 (그리고 둘 다 C 표준에 따라 정확합니다).

유일한 가지고 다닐 수 있는 포인터 값을 인쇄하는 방법은 "%p" 구현 정의 출력을 생성하는 지정자. (변환 uintptr_t 그리고 사용 PRIxPTR 일할 가능성이 있지만 (a) uintptr_t C99에 도입되었으므로 일부 컴파일러는이를 지원하지 않을 수 있으며 (b) C99에도 존재하는 것이 보장되지 않습니다 (가능한 모든 포인터 값을 보유 할 수있을만큼 큰 정수 유형이 없을 수도 있습니다.

그래서 사용하십시오 "%p" ~와 함께 sprintf() (또는 snprintf(), 당신이 그것을 가지고 있다면) 문자열에 인쇄 한 다음, 끈 패딩을 선도 블랭크로 인쇄하십시오.

한 가지 문제는 "%p".

이것은 불편하다 (물론 함수로 랩핑 할 수 있지만). 100% 휴대 성이 필요하지 않으면 시스템을 사용한 적이 없습니다. unsigned long 그리고 결과를 인쇄합니다 "0x%16lx" 작동하지 않을 것입니다. [의 뜻업데이트: 네, 있어요. 64 비트 창에는 64 비트 포인터와 32 비트가 있습니다 unsigned long.] (또는 사용할 수 있습니다 "0x%*lx" 그리고 아마도 너비를 계산합니다 sizeof (void*) * 2. 정말 편집증이라면 시스템을 설명 할 수 있습니다. CHAR_BIT > 8, 따라서 바이트 당 26 진수 이상을 얻을 수 있습니다.)

이 답변은 이전에 주어진 것과 유사합니다. https://stackoverflow.com/a/1255185/1905491 또한 가능한 너비를 고려합니다 (요약 한대로 https://stackoverflow.com/a/6904396/1905491 내 대답이 아래로 표시 될 때까지 인식하지 못했습니다.). 다음 Snipped는 Pointers를 Sane* 기계에서 8 개의 0 헥스 문자로 인쇄하여 32 비트, 64b에서 16 개, 16B 시스템에서 4 개로 표현할 수 있습니다.

#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))

printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);

C99 (아마도?)에있는 다음 인수에 의해 너비를 가져 오기 위해 별표 문자의 사용에 주목하십시오. 이것은 사용하는 것보다 훨씬 낫습니다 p 후자는 구현 정의이기 때문에 변환.

* 표준이 허용됩니다 uintptr_t 최소값보다 크지 만 최소값을 사용하지 않는 구현이 없다고 가정합니다.

포인터를 긴 유형으로 캐스팅하면 쉽게 해결할 수 있습니다. 문제는 포인터가 긴 안에 들어갈 수 있고 포인터를 16 자 (64 비트)로 표시 할 수 있다고 가정하므로 모든 플랫폼에서 작동하지 않는다는 것입니다. 그러나 이것은 대부분의 플랫폼에서 사실입니다.

그래서 그것은 다음과 같습니다.

printf("%016lx", (unsigned long) ptr);

링크에서 이미 제안한 것처럼 행동은 정의되지 않습니다. %P 자체가 작업중 인 플랫폼에 의존하기 때문에 휴대용이 작업을 수행하는 휴대용 방법이 없다고 생각합니다. 물론 포인터를 int에 시전하고 16 진로 표시 할 수 있습니다.

printf("0x%016lx", (unsigned long)ptr);

어쩌면 이것은 흥미로울 것입니다 (Mingw를 사용하여 32 비트 Windows 시스템에서) :

rjeq@RJEQXPD /u
$ cat test.c
#include <stdio.h>

int main()
{
    char c;

    printf("p: %016p\n", &c);
    printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);

    return 0;
}

rjeq@RJEQXPD /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format

rjeq@RJEQXPD /u
$ ./test.exe
p:         0022FF77
x: 000000000022ff77

보시다시피, %P 버전 패드는 포인터 크기의 0 인 다음 지정된 크기로의 공백을 갖는 반면, %X 및 캐스트 (캐스트 및 형식 지정자는 고정 할 수 없음)는 0 만 사용합니다.

포인터가 "0x"접두사로 인쇄하는 경우 보상하기 위해 "%018p"를 대체해야합니다.

나는 보통 %x를 사용하여 포인터를 표시합니다. 64 비트 시스템으로는 휴대용이 아니라고 생각하지만 32 비트에 적합합니다.

나는 거기에 무엇이 있는지보고 싶을 것입니다 휴대용 솔루션, 포인터 표현은 휴대용이 아니기 때문에.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top