[解決済み】ポインタまたはアドレスを印刷するための正しいフォーマット指定子?
質問
変数のアドレスを表示するには、どの書式指定子を使えばよいのでしょうか?以下のロットで迷っています。
<ブロッククオートu - 符号なし整数
x - 16進数値
p - void ポインタ
アドレスを印刷するのに最適な形式はどれでしょうか?
どのように解決するのですか?
最もシンプルな答えは、異なるプラットフォーム間のフォーマットのばらつきや差異を気にしないと仮定すれば、標準的な
%p
という表記があります。
C99規格(ISO/IEC 9899:1999)では、§7.19.6.1 ¶8でこう言っています。
p
へのポインタを引数とする。void
. ポインタの値は は,実装の定めるところにより,一連の印刷文字に変換される。 の方法で行う。
(C11 - ISO/IEC 9899:2011 - では §7.21.6.1 ¶8 に記載されています)。
一部のプラットフォームでは、先頭の
0x
また、文字は小文字でも大文字でもよく、C標準では16進数で出力するように定義されていませんが、そうでない実装を私は知りません。
で明示的にポインタを変換するべきかどうかは、議論の余地があります。
(void *)
を鋳造します。 これは明示的であり、通常は良いことです(だから私はそうしています)。
void
'. ほとんどのマシンでは、明示的なキャストを省略することができます。 しかし、ビット表現で
char *
のアドレスは、与えられたメモリ位置の'
その他のポインタ
のアドレスは、同じメモリ位置に対するものです。 これは、バイトアドレスではなく、ワードアドレスのマシンとなります。 このようなマシンは最近ではあまり見かけなくなりましたが、私が大学卒業後に最初に携わったマシン(ICL Perq)がそのようなものでした。
の実装で定義された挙動に満足できない場合は、以下のようにします。
%p
の場合、C99を使用します。
<inttypes.h>
と
uintptr_t
の代わりに
printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);
これによって、表現を自分に合ったものに微調整することができます。 私は、16進数の数字を大文字にすることで、数字の高さが一様に同じになるようにし、冒頭の特徴的なディップは
0xA1B2CDEF
のようなものではなく、このように表示されます。
0xa1b2cdef
も数字に沿って上下に凹む。 しかし、非常に広い範囲内で、あなたの選択です。 その
(uintptr_t)
のキャストは、GCCがコンパイル時にフォーマット文字列を読み取ることができる場合、明確に推奨されています。 警告を無視して、たいていの場合逃げ出す人もいると思いますが、キャストを要求するのは正しいことだと思います。
ケレクさんがコメントで質問しています。
標準のプロモーションと変種引数について少し混乱しています。すべてのポインターはvoid*に標準プロモートされるのでしょうか?そうでなければ、もし
int*
が例えば2バイトでvoid*
が4バイトだった場合、引数から4バイトを読み取るのは明らかにエラーですよね?
C言語規格では、オブジェクトのポインタはすべて同じサイズでなければならないとされているように錯覚していましたので
void *
と
int *
を異なるサイズにすることはできません。 しかし、私がC99規格の関連セクションと考えるものは、それほど強調されていません(ただし、私が提案したことが実際に間違っている実装を私は知りません)。
§6.2.5 タイプ
¶26 voidへのポインタは、文字型へのポインタと同じ表現とアラインメントの要件を持つものとする。 39) 同様に、互換型の修飾版または非修飾版へのポインタも、同じ表現と配置の要件を持つものとする。構造体型へのすべてのポインタは,互いに同じ表現及び整列の要求をもたなければならない。和集合型へのすべてのポインタは,互いに同じ表現及び整列の要求をもたなければならない。他の型へのポインタは,同じ表現又は整列の要求事項をもつ必要はない。
39) 同じ表現と配置の要件は、関数の引数、関数の戻り値、組合のメンバーとして交換可能であることを意味する。
(C11では§6.2.5, ¶28, 脚注48で全く同じことを言っている)。
したがって、構造体へのポインタはすべて互いに同じサイズでなければならず、ポインタが指す構造体のアライメント要件が異なっていても、同じアライメント要件を共有しなければなりません。 ユニオンの場合も同様です。 文字ポインタとvoidポインタは、同じサイズとアライメント要件でなければなりません。 のバリエーションへのポインターは
int
(意味
unsigned int
と
signed int
) は、互いに同じサイズとアライメントの要件を持たなければなりません。他の型についても同様です。 しかし、C言語規格では、正式に
sizeof(int *) == sizeof(void *)
. そうか、SOは自分の思い込みを点検させるのに適しているんだ。
C言語規格では、関数ポインタとオブジェクトポインタが同じサイズであることを決定的に要求していません。 これは、DOSのようなシステムで異なるメモリモデルを壊さないようにするために必要なことでした。 16ビットのデータポインタがあっても32ビットの関数ポインタがあったり、その逆もあり得るのです。 このため、C言語規格では、関数ポインタをオブジェクトポインタに変換したり、その逆を行うことは義務づけていません。
POSIXをターゲットにしているプログラマにとっては)幸いなことに、POSIXがこの問題に踏み込んで、関数ポインタとデータポインタを同じサイズにすることを義務付けています。
<ブロッククオート§2.12.3 ポインターの種類
すべての関数ポインタの型は,voidへの型ポインタと同じ表現を持たなければならない。関数ポインタの
void *
は,その表現を変更してはならない。A
void *
このような変換によって得られた値は、情報を失うことなく、明示的なキャストを用いて元の関数ポインタ型に戻すことができます。
注 ISO C 標準では要求されていませんが、POSIX 準拠のためには必要です。
ということで、どうやら、明示的なキャストで
void *
のような可変個体関数へのポインタを渡す場合、コードの信頼性を最大にするために強く推奨されます。
printf()
. POSIX システムでは、関数ポインタを void ポインタにキャストして印刷することは安全です。 他のシステムでは,必ずしもそうすることが安全とは限りませんし,ポインタを
void *
をキャストせずに使用します。
関連
-
[解決済み] c - 初期化がキャストなしでポインタから整数を作る、さらに2つのコンパイラーエラー
-
[解決済み] strtokのセグメンテーションフォールト
-
[解決済み] printf ファミリーを使用して、size_t 変数をポータブルに印刷するにはどうすればよいですか?
-
[解決済み] C 言語で int64_t 型を表示する方法
-
[解決済み] 型付けされた関数ポインタ?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] どうすれば、文字列中のリテラルな中抜き文字を印刷し、また.formatを使用することができるのでしょうか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] 浮動小数点以下の0を削除して文字列に変換する方法
-
[解決済み] C言語でのポインタ:アンパサンドとアスタリスクはいつ使うのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】単項演算子「*」の型が無効(「int」がある)C言語でのエラー
-
[解決済み】strcmpが機能しない
-
[解決済み】C言語におけるファイルスコープでの可変長配列の変更
-
[解決済み】C 未知の型名「my_structure」。
-
[解決済み】警告:組み込み関数'printf'の非互換な暗黙の宣言(デフォルトで有効]
-
[解決済み】 「配列のイニシャライザーはイニシャライザーリストまたは文字列リテラルでなければなりません」と表示されるのですが?
-
[解決済み】エラー:不明な型名'bool'
-
[解決済み】0LLや0x0ULの意味は何ですか?
-
[解決済み】makefile:4。*** missing separator. 停止する
-
[解決済み】Linuxソケットのwrite()でBad File Descriptorが発生するC