Cでは、ポインターを表示するためにprintfを使用し、それらが正しく整列するように、0で埋めたいと思います。
私の推測では、これを行う適切な方法は次のとおりです。
printf( "%016p"、ptr);
これは機能しますが、このgccは次のメッセージを表示します。
警告: '%p' gnu_printf形式で '0'フラグが使用されています
私はそれを少しググってみました、そして次のスレッドは同じトピックについてですが、本当に解決策を与えません。
http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html
それを読んで、gccが文句を言う理由は、私が提案した構文がC99で定義されていないためだと思われます。しかし、標準の承認された方法で同じことを行う他の方法を見つけることができないようです。
だからここに二重の質問があります:
_#include <inttypes.h>
_
_#include <stdint.h>
_
printf("%016" PRIxPTR "\n", (uintptr_t)ptr);
ただし、実装で定義された方法でポインタを出力しません(8086セグメントモードの場合は_DEAD:BEEF
_と表示されます)。
使用する:
_#include <inttypes.h>
printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);
_
または、そのヘッダーのマクロの別のバリアントを使用します。
また、printf()
の一部の実装では、ポインタの前に '_0x
_'が出力されます。他の人はそうしません(そして両方ともC標準に従って正しいです)。
ポインター値を出力する唯一のportable方法は、実装定義の出力を生成する_"%p"
_指定子を使用することです。 (_uintptr_t
_への変換とPRIxPTR
の使用は機能する可能性がありますが、(a)_uintptr_t
_はC99で導入されたため、一部のコンパイラではサポートされていない可能性があり、(b)保証されていませんC99にも存在する(可能なすべてのポインター値を保持するのに十分な大きさの整数型がない場合があります)。
そのため、_"%p"
_をsprintf()
(またはsnprintf()
(ある場合)とともに使用して文字列に出力し、その後に先行空白で文字列のパディングを出力します。
1つの問題は、_"%p"
_によって生成される文字列の最大長を決定する本当に良い方法がないことです。
これは確かに不便です(もちろん、関数でラップすることもできます)。 100%の移植性が必要ない場合、_unsigned long
_へのポインターをキャストするシステムを使用したことがなく、_"0x%16lx"
_を使用して結果を印刷しても機能しません。 [[〜#〜] update [〜#〜]:はい、持っています。 64ビットWindowsには64ビットポインターと32ビット_unsigned long
_があります。](または、_"0x%*lx"
_を使用して幅を計算できます。おそらくsizeof (void*) * 2
のようになります。本当に偏執的で、_CHAR_BIT > 8
_であるシステムを考慮することができるので、バイトあたり2桁を超える16進数が得られます。)
この回答は、以前に https://stackoverflow.com/a/1255185/1905491 で与えられたものと似ていますが、可能な幅も考慮に入れています(- https:// stackoverflow.com/a/6904396/1905491 私の答えがその下に表示されるまで私はそれを認識しませんでした;)次の抜粋は、sane *マシンでポインターを8つの0で渡された16進文字として出力します。これらのポインターは、32ビットで表現でき、64bでは16ビット、16bシステムでは4ビットで表すことができます。
#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);
次の引数によって幅をフェッチするためのアスタリスク文字の使用に注意してください。これはC99(おそらく前?)にありますが、「実際には」ほとんど見られません。後者は実装定義なので、p
変換を使用するよりもはるかに優れています。
*標準ではuintptr_t
は最小値よりも大きくなりますが、最小値を使用しない実装はないと思います。
多分これは面白いでしょう(32ビットのWindowsマシンから、mingwを使用して):
rjeq@RJEQXPD /u
$ cat test.c
#include <stdio.h>
int main()
{
char c;
printf("p: %016p\n", &c);
printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);
return 0;
}
rjeq@RJEQXPD /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format
rjeq@RJEQXPD /u
$ ./test.exe
p: 0022FF77
x: 000000000022ff77
ご覧のように、%pバージョンでは、ポインターのサイズまでゼロが埋め込まれ、指定されたサイズまでスペースが挿入されますが、%xとキャスト(キャストとフォーマット指定子は非常に移植性が低い)を使用すると、ゼロのみが使用されます。
ポインターが "0x"プレフィックスで印刷される場合は、補正するために "%018p"に置き換える必要があることに注意してください。
ポインタをlong型にキャストすると、簡単に解決できます。問題は、ポインターがlongの内部に収まり、ポインターが16文字(64ビット)で表示されることを想定しているため、すべてのプラットフォームで機能しないことです。ただし、これはほとんどのプラットフォームに当てはまります。
したがって、次のようになります。
printf("%016lx", (unsigned long) ptr);
リンクがすでに示唆しているように、動作は未定義です。 %p自体は作業しているプラットフォームに依存するため、これを行うポータブルな方法はないと思います。もちろん、ポインタをintにキャストして16進数で表示することもできます。
printf("0x%016lx", (unsigned long)ptr);