programing

0으로 채워진 포인터를 표시하기 위해 printf를 사용하는 올바른 방법은 무엇입니까?

javaba 2022. 7. 2. 23:58
반응형

0으로 채워진 포인터를 표시하기 위해 printf를 사용하는 올바른 방법은 무엇입니까?

C에서는 printf를 사용하여 포인터를 표시하고 올바르게 정렬할 수 있도록 0으로 패딩하고 싶습니다.

적절한 방법은 다음과 같습니다.

printf(%)%016p", printf (%016p),

이것은 동작합니다만, 이 gcc는 다음과 같은 메시지로 불만을 제기합니다.

경고: '0' 플래그가 '%p' gnu_printf 형식과 함께 사용되었습니다.

구글에서 검색해 봤는데 다음 스레드는 같은 주제에 있지만 해결 방법이 없습니다.

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:BEEF8086 세그먼트 모드).

이 답변은 https://stackoverflow.com/a/1255185/1905491에서 이전에 제시한 답변과 비슷하지만 가능한 폭도 고려합니다(https://stackoverflow.com/a/6904396/1905491에서 설명한 바와 같이, 답변이 아래에 렌더링될 때까지 몰랐습니다).다음 슬라이드는 sane*머신에서 포인터를 8개의 0-pass 16진수로 인쇄합니다.이러한 포인터는 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최소값보다 클 수 있지만 최소값을 사용하지 않는 구현은 없을 것입니다.

용도:

#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비트 Windows에는 64비트 포인터와 32비트가 있습니다.unsigned long.] (또는"0x%*lx"너비를 계산하면 아마 다음과 같은 것이 될 것입니다.sizeof (void*) * 2정말 편집증적인 경우, 다음과 같은 시스템을 설명할 수 있습니다.CHAR_BIT > 8바이트당 16진수를 2자리 이상 얻을 수 있습니다.)

긴 글씨로 포인터를 던지면 쉽게 풀 수 있습니다.문제는 포인터가 긴 안쪽에 들어갈 수 있고 포인터가 16자(64비트)로 표시될 수 있다고 가정하기 때문에 모든 플랫폼에서는 작동하지 않는다는 것입니다.단, 이는 대부분의 플랫폼에서 해당됩니다.

그러면 다음과 같이 됩니다.

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

링크에서 이미 알 수 있듯이 동작은 정의되어 있지 않습니다.%p 자체는 작업 중인 플랫폼에 따라 다르기 때문에 휴대용 방법은 없는 것 같습니다.물론 포인터를 int에 던져 16진수로 표시할 수도 있습니다.

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

아마 이것은 흥미로울 것입니다(32비트 Windows 머신에서 mingw를 사용).

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비트 시스템에서는 정상적으로 작동합니다.

포인터 표현은 정확하게 휴대할 수 없기 때문에 휴대용 솔루션에 대한 답변이 있는지 알고 싶습니다.

언급URL : https://stackoverflow.com/questions/1255099/whats-the-proper-use-of-printf-to-display-pointers-padded-with-0s

반응형