формат строки для intptr_t и uintptr_t - PullRequest
28 голосов
/ 27 апреля 2011

Что такое формат строки для intptr_t и uintptr_t, который действителен как для 32-, так и для 64-битной архитектуры.

EDIT

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

Это предупреждение, которое я получаю в 64-битном, но не в 32-битном.

  intptr_t  AAA

Ответы [ 6 ]

45 голосов
/ 27 апреля 2011

Это будут следующие макросы из 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);
2 голосов
/ 17 сентября 2018

Я думаю, вам следует рассмотреть возможность использования модификатора 'z'. Это преобразует все, что соответствует size_t или ssize_t, и я обнаружил, что это работает и с (u) intptr_t.

Например:

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

0 голосов
/ 31 октября 2017
####################################### 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;
}
0 голосов
/ 26 мая 2017

Я думаю, что даже long int небезопасно, и вы должны попробовать long long int, который должен существовать, потому что вы работаете над 64-битной архитектурой, и у вас уже есть intptr_t.

На некоторых 64-битная архитектура (я думаю, что Microsoft Windows так и будет), long int может храниться в 32-битной ширине, чтобы соответствовать предположению возраста MS-DOS, что short int всегда 16-битный, а long int всегда 32-bit.

Даже на тех платформах с 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-разрядных целых чисел.

PS %p в этом случае может оказаться неэффективным, поскольку %p может печатать голое слово 0x перед шестнадцатеричными числами и/ или может напечатать заполненное нулями значение.Например, если применяются оба варианта, код printf("%p\n", (void*)16); будет печатать 0x00000010 на 32-битных платформах и 0x0000000000000010 на 64-битных платформах;постер должен был надеяться, что будет напечатано 10.

0 голосов
/ 27 января 2017

%p должен работать вместо %x, поскольку uintptr_t определено как целое число без знака с таким же размером, что и указатель на платформе.

РЕДАКТИРОВАТЬ: К сожалению, по крайней мере на моем компиляторе вы должны привести переменную к (void *). Тем не менее, я думаю, что безопасно приводить uintptr_t к указателю.

0 голосов
/ 15 января 2016

Я компилирую некоторый код в среде, которая по какой-то причине не имеет макросы PRI.PTR, определенные в inttypes.h, и в которых intptr_t определяется как int в 32бит и long int в 64 бит.

Я взломал предупреждения, используя спецификатор формата %li и приведя переменные к long int в параметрах printf.Это безопасно в этой среде , поскольку intptr_t никогда не может быть длиннее long int, как описано выше.

Я бы не рекомендовал использовать это решение, если вы можете избежать его, но это, по крайней мере, устраняет предупреждения.

...