programing

intptr_t 및 uninttr_t의 문자열 형식

i4 2023. 8. 29. 20:08
반응형

intptr_t 및 uninttr_t의 문자열 형식

의 문자열 형식은 무엇입니까?intptr_t그리고. uintptr_t이는 32비트 및 64비트 아키텍처 모두에 유효합니다.

편집

warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type "AAA"

이것은 제가 64비트에서 받고 있는 경고이지만 32비트에서는 받지 않습니다.

  intptr_t  AAA

그것은 다음의 매크로일 것입니다.inttypes.h:

위해서printf:PRIdPTR PRIiPTR PRIoPTR PRIuPTR PRIxPTR PRIXPTR

위해서scanf:SCNdPTR SCNiPTR SCNoPTR SCNuPTR SCNxPTR

사용 예:

uintptr_t p = SOME_VALUE;
printf("Here's a pointer for you: %" PRIxPTR "\n", p);

저는 당신이 'z' 수식어를 사용하는 것을 고려해야 한다고 생각합니다.이렇게 하면 size_togsize_t에 해당하는 모든 것이 변환되며, (u)inttr_t에서도 작동한다는 것을 알게 되었습니다.

예:

intptr_tip = ...printf("ip = %zd\n", ip);

%p의 대체품으로 작동해야 합니다.%x,부터uintptr_t플랫폼의 포인터와 같은 크기의 부호 없는 정수로 정의됩니다.

편집: 불행히도 적어도 내 컴파일러에서는 변수를 (void *)에 캐스팅해야 합니다.하지만 포인터에 uinttr_t를 캐스트하는 것이 안전하다고 생각합니다.

####################################### CPP type proving code (identifying type by typeid)
$ cat typeid.cpp
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>
#include <typeinfo>

#define name(t) printf("%30s : %s\n", #t, typeid(t).name())

// g++|clang++ -o ./typeid.exe typeid.cpp -m32 && ./typeid.exe
// g++|clang++ -o ./typeid.exe typeid.cpp -m64 && ./typeid.exe
int main(int argc, char* argv[]) {
    name(ptrdiff_t);
    name(intptr_t);
    name(uintptr_t);

    return 0;
}

####################################### C type proving code (identifying type by _Generic)
$ cat typeid.c 
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <time.h>

/* matches the type name of an expression */
#define name_match(e) _Generic((e), \
                 _Bool: "_Bool", \
                  char: "char", \
           signed char: "signed char", \
         unsigned char: "unsigned char", \
                 short: "short", \
        unsigned short: "unsigned short", \
                   int: "int", \
          unsigned int: "unsigned int", \
                  long: "long", \
         unsigned long: "unsigned long", \
             long long: "long long", \
    unsigned long long: "unsigned long long", \
                 float: "float", \
                double: "double", \
           long double: "long double", \
               default: "unknown")

#define name(t, e) printf("%30s : %s\n", #t, name_match(e))

int main() {
    ptrdiff_t ptrdiff_v = 0;
    intptr_t  intptr_v = 0;
    uintptr_t uintptr_v = 0;

    name(ptrdiff_t, ptrdiff_v);
    name(intptr_t,  intptr_v);
    name(uintptr_t, uintptr_v);
}

####################################### run in arch32
$ clang++ -o ./typeid.exe typeid.cpp -m32 && ./typeid.exe
                     ptrdiff_t : i
                      intptr_t : i
                     uintptr_t : j

$ clang -o ./typeid.exe typeid.c -m32 && ./typeid.exe      
                     ptrdiff_t : int
                      intptr_t : int
                     uintptr_t : unsigned int
result:
     intptr_t == ptrdiff_t
    uintptr_t == unsigned ptrdiff_t

####################################### run in arch64
$ clang++ -o ./typeid.exe typeid.cpp -m64 && ./typeid.exe
                     ptrdiff_t : l
                      intptr_t : l
                     uintptr_t : m

$ clang -o ./typeid.exe typeid.c -m64 && ./typeid.exe   
                     ptrdiff_t : long
                      intptr_t : long
                     uintptr_t : unsigned long
result:
     intptr_t == ptrdiff_t
    uintptr_t == unsigned ptrdiff_t

####################################### man 3 printf
t -- A following integer conversion corresponds to a ptrdiff_t argument.

####################################### conclusion
//  intptr_t == ptrdiff_t
// uintptr_t == unsigned ptrdiff_t
// so:
//     1)  intptr_t has string format %td
//     2) uintptr_t has string format %tu

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
    intptr_t  x = 0;
    uintptr_t y = 0;

    scanf("%td %tu", &x, &y);
    printf("out: %td %tu\n", x, y);
    return 0;
}

나는 어떤 이유에서인지 없는 환경에서 코드를 컴파일하고 있습니다.PRI.PTR정의된 매크로inttypes.h그리고 그 안에서intptr_t로 정의됩니다.int32비트로long int64비트로.

나는 사용하여 경고를 해킹했습니다.%li형식 지정자 및 변수 캐스팅 대상long int에서printf매개 변수환경에서는 안전합니다. 왜냐하면intptr_t절대 a보다 길 수 없습니다.long int상술한 바와 같이

피할 수 있다면 이 솔루션을 사용하는 것을 권장하지는 않지만, 적어도 경고는 해결되었습니다.

내 생각엔 심지어long int안전하지 않습니다, 그리고 당신은 노력해야 합니다.long long int64비트 아키텍처에서 작업 중이고 현재 사용 중이기 때문에 존재해야 합니다.intptr_t이미.

일부 64비트 아키텍처(Microsoft Windows도 그럴 것으로 생각됨)에서는long intMS-DOS 시대의 가정을 만족시키기 위해 32비트 폭으로 유지할 수 있습니다.short int항상 16비트이며long int는 항상 32비트입니다.

32비트 플랫폼에서도long int,printf("%llx", (unsigned long long)AAA);효과가 있을 것입니다.그리고 당신은 더 선호하는 형태를 고려해야 합니다.printf("%jx", (uintmax_t)AAA);가능하면.

일부 오래된 컴파일러의 경우 사용해야 할 수 있습니다."%Lx"(GNU C의 경우, 캐스팅 포함)unsigned long long) 또는"%I64x"(Visual C++의 경우, 캐스팅 포함)__uint64)(64비트 정수의 경우).

추신.%p이 경우에는 좋지 않을 수 있습니다, 왜냐하면%p맨 단어를 인쇄할 수 있습니다.0x16진수 앞에 표시하거나 0-숫자 값을 인쇄할 수 있습니다.둘 다 적용되는 경우, 예를 들어 코드는printf("%p\n", (void*)16);인쇄 예정0x0000001032비트 플랫폼 및0x000000000000001064비트 플랫폼에서; 포스터는 그저 바라야 했습니다.10

언급URL : https://stackoverflow.com/questions/5795978/string-format-for-intptr-t-and-uintptr-t

반응형