intptr_t
和uintptr_t
在32位和64位体系结构中的字符串格式是什么?
编辑:
warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type "AAA"
我在64位系统上收到了这个警告,但在32位系统上没有。
intptr_t AAA
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_t 或 ssize_t 相对应的任何内容转换,并且我发现它也适用于 (u)intptr_t。
例如:
intptr_t ip = ...; printf("ip = %zd\n", ip);
void *p = ...; printf("%td", (ptrdiff_t)p);
会产生(同样类型的)未定义行为吗? - dxiv####################################### 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;
}
typeid
在 C 中不存在,所以...... - Stargateur%p
应该可以替换 %x
,因为在该平台上,uintptr_t
被定义为与指针大小相同的无符号整数。
编辑:不幸的是,在我的编译器上,您必须将变量转换为(void *)。但是,我认为将 uintptr_t 转换为指针是安全的。
我正在一个环境中编译一些代码,但由于某种原因,inttypes.h
中的 PRI.PTR
宏未定义,并且在其中 intptr_t
在 32 位上被定义为 int
,在 64 位上被定义为 long int
。
我通过在 printf
参数中使用 %li
格式说明符并将变量强制转换为 long int
来解决了警告。在这个环境中,这是安全的,因为如上所述,intptr_t
永远不会比 long int
更长。
如果可以避免,我不建议使用这种解决方案,但至少它解决了警告。
我认为即使是long int
也不安全,你应该尝试使用long long int
,因为你正在使用64位架构并且已经有了intptr_t
。
在一些64位架构上(我认为微软Windows就是这样),long int
可能会保持32位宽度,以满足MS-DOS时代的假设,即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
可能会在十六进制数之前打印裸字 0x
,并/或者可能会打印零填充值。如果两者都应用了,例如,代码 printf("%p\n", (void*)16);
将在 32 位平台上打印 0x00000010
,在 64 位平台上打印 0x0000000000000010
;发帖人应该希望只打印 10
。
uinptr_t p = SOME_VALUE; printf("这是一个指针:% " PRIxPTR "\n", p);
- Fred Foo