結局のところ、これらのステートメントは両方とも同じことをします...
int a = 10;
int *b = &a;
printf("%p\n",b);
printf("%08X\n",b);
例(異なるアドレス):
0012FEE0
0012FEE0
%x
を使用してポインタを希望どおりにフォーマットするのは簡単です。したがって、%p
オプションを使用する方法はありますか?
彼らは同じことをしません。後者の printf
ステートメントはb
をunsigned int
として解釈しますが、b
はポインターであるため間違っています。
ポインターとunsigned int
sは常に同じサイズではないため、これらは互換性がありません。それらが同じサイズではない場合(64ビットCPUとオペレーティングシステムが一般的になるにつれて、ますます一般的なケース)、%x
はアドレスの半分のみを出力します。 Mac(およびおそらく他のシステム)では、そのwillはアドレスを台無しにします。出力は間違っています。
ポインターには常に%p
を使用します。
少なくとも珍しいことではない1つのシステムでは、同じものは印刷されません。
~/src> uname -m
i686
~/src> gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
[some output snipped]
gcc version 4.1.2 (Gentoo 4.1.2)
~/src> gcc -o printfptr printfptr.c
~/src> ./printfptr
0xbf8ce99c
bf8ce99c
たとえば、ポインターバージョンが0x
プレフィックスを追加する方法に注目してください。ポインタのサイズと、それらをテキストとして最適に表現する方法を知っているため、常に%pを使用します。
%p
プレフィックスを表示する0x
に依存することはできません。 Visual C++では、そうではありません。 %#p
を使用して移植可能にします。
ポインターのサイズは、int
のサイズとは異なる場合があります。また、%p
を使用すると、実装はアドレスの単純な16進値表現よりも優れた結果を生成できます。
デバッグする必要があるときは、%p
オプションを指定してprintfを使用すると非常に便利です。 NULL値がある場合、0x0が表示されます。