####################################### 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;
}