一般に…
int *x = (int*)0xdeadbeef
こんな風にポインタのアドレスを直接指定するコードが散見されますが、C99 によると、整数値からポインタへの変換は処理系定義とのことなので、確実性がないように思います。
https://www.jpcert.or.jp/m/sc-rules/c-int36-c.html
こちらにそのことが詳しく書かれています
(「適切に境界調整されないかもしれないし、被参照型のエントリを指していないかもしれないし、あるいはトラップ表現になるかもしれない。」とのことですが、これの意味はちょっとよく分かってないです)。
そこで、適合コードによると、
volatile uintptr_t iptr = 0xdeadbeef;
int *x = (int*)iptr;
とすれば、「コンパイラが整数値を適切なポインタ値に変換する役に立つかもしれない」とのことです。
質問は2点あります。
① iptr を volatile 宣言する理由が分かりません。不要ではないでしょうか。何か問題が起きますか。
② uintptr_t から int* への変換は規定がない(?)ので、int *x = (int*)(void*)iptr とすべきではないでしょうか。
以上です。
お分かりになる方、ご回答よろしくお願いします。
No.7ベストアンサー
- 回答日時:
まず結論を簡潔に書く.
どうせなにをどうやっても規格上動作は保証できないんだから
int *x = (int *)0xdeadbeef;
で十分. 何をどうこねたところで話は変わらない以上, まわりくどく面倒な書き方をする必要はない.
で 1つずついくと
・0xdeadbeef の型のサイズが uintptr_t より小さかったらどうなるか: たぶん 0 拡張されたうえでポインタ型に変換されるだろうけど, もとより「規格では何も決めていない」のだからどうなるかなどわかりようもない. ちなみに sizeof (uintptr_t) と sizeof(void *) の大小関係も決まってない.
・最適化のあたり: volatile の意味は理解できていますか... と書いておくけど, これもはっきりいってここでは無関係だしな~.
・アラインメント: ここは表現の微妙な違いを味わってほしいところ. #2 では
アライメントも考えた
となっているのに対し #6 では
アラインメントを「考慮」した
となっている.
あ, 「適合」のところは
気のせいなので忘れてあげる
べきだと思います>#5.
No.8
- 回答日時:
アドレスを直接指定している場合、
コンパイラが勝手に整数値を適切なポインタ値に変換してくれたら
困るんじゃないの?
アラインメントエラーでコアダンプになったほうが数倍ましというか。
No.6
- 回答日時:
例えば
volatile uintptr_t iptr = 0xdeadbeef;
int *x = (int*)(void*)iptr;
が「処理系定義の動作」かどうかというと, 結論的には「処理系定義」です. 規格上保証されているのは
void * の値を uintptr_t に変換して void * に戻すと元と同じ
であって, 今の例とは異なるのでこの条件には当てはまりません. で, 当てはまる文面を探すと
整数を任意のポインタ型に変換できる (may be conerted)
があって, 結果として (void *) の有無にかかわらずこの場面では「処理系定義」でしかありません.
volatile があるのは #2 で指摘されているように「最適化対策」でしょう (「それは本来の volatile の用途じゃない」と突っ込まれそうだが). volatile がないと
uintptr_t iptr = 0xdeadbeef;
int *x = (int *)0xdeadbeef;
という最適化が可能なので.
あと, この 0xdeadbeef という値はおそらく
アラインメントを「考慮」した (& 英語として「読める」) 値
のはず>#2.
というか, そもそもとして uintptr_t の存在を前提にしていいのか?
理解できた気がしました。
uintptr_t型の整数 0xdeadbeef が、ポインタ値としての 0xdeadbeef 番地であるとは限らない、その点が処理系定義ということですね。
規格上の保証は、
int a;
uintptr iptr = (uintptr_t)(void*)&a;
int *x = (int*)(void*)iptr;
assert(&a == x);
ということですかね。
整数を任意のポインタ型に変換できる、ということは、どう書こうが処理系定義だから、
int *x = (int*)0xdeadbeef
これで構わないということでしょうか。
掲題のページで「コンパイラが整数値を適切なポインタ値に変換する役に立つかもしれない」とあるのは、整数定数 0xdeadbeef の型のサイズが、uintptr_t の型のサイズより小さい場合、うまくいかないかもしれないよ、ということを言いたいような気がしました。
volatile がないときに
uintptr_t iptr = 0xdeadbeef;
int *x = (int *)0xdeadbeef;
という最適化がされるのであれば、x に代入されるアドレスは
uintptr_t iptr = 0xdeadbeef;
int *x = (int *)iptr;
としたときと同じになる場合ではないですか?
であれば、その最適化には問題がないと思います。
アライメントを考慮したのであれば、intが4バイトの環境では、4の倍数になるのでは?
どんな環境の仮定かは分かりませんが、0xdeadbeef = 11 * 257 * 1321517 なので、アライメントを考慮してないように思います。
とりあえず、uintptr_t の存在は仮定します。
No.5
- 回答日時:
リンク先の適合コードというのがどの程度妥当なのか疑問ですね。
アドレスを即値で指定する時点で、処理系の如何に関わらずデバイス依存性の強いコードなので処理系依存でも構わないでしょう。
No.3
- 回答日時:
>iptr の方を volatile しているのは、なぜなのでしょうか?
int *x = (int*)iptr;
が実行されないかもしれません。
>volatile int *xであれば、
int *x = (int*)iptr;
された後なので、おおもとのデータが変わっても、x のデータは変わりません。
最適化しても問題ないと思います。
ん・・・ここは
コメントはツリーに出来ないのかな?
まいいか。
No.2
- 回答日時:
仮想記憶とかあると、アドレス直接指定は無意味になりますが、
絶対アドレスを指定できるなら特に問題は無いかと。
ただ、0xdeadbeef;の様な奇数番地は、int には使えないかもしれません。
アライメントも考えた番地にしましょう。
volatile 宣言は、コンパイラの最適化対策です。
コンパイラのソースコード中で変更していないデータは、
値が変わることが無いので、無視・または飛ばされることがあります。
volatile付けることで、
割り込みでのデーター変化や、外部IOなどからのデータ変更がある、
常に監視しておかなければいけないデータ領域であることを、
コンパイラに教えます。
アライメントの問題、失礼しました。
気をつけます。
volatile int *x
であれば、0xdeadbeef の指す先が外的要因で変化することを知らせていることになると思うのですが、
iptr の方を volatile しているのは、なぜなのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# 変数のスコープ 5 2023/05/27 17:50
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語 ポインタ 配列 2 2022/06/02 17:29
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C pointer? or... 2 2022/03/29 00:47
このQ&Aを見た人はこんなQ&Aも見ています
-
カンパ〜イ!←最初の1杯目、なに頼む?
飲み会で最初に頼む1杯、自由に頼むとしたら何を頼みますか? 最初はビールという縛りは無しにして、好きなものを飲むとしたら何を飲みたいですか。
-
あなたにとってのゴールデンタイムはいつですか?
一週間の中でもっともテンションが上がる「ゴールデンタイム」はいつですか? その逆で、一週間でもっとも落ち込むタイミングでも構いません。 よかったら教えて下さい!
-
遅刻の「言い訳」選手権
よく遅刻してしまうんです…… 「電車が遅延してしまい遅れました」 「歯医者さんが長引いて、、、」 「病院が混んでいて」 などなどみなさんがこれまで使ってきた遅刻の言い訳がたくさんあるのではないでしょうか?
-
牛、豚、鶏、どれか一つ食べられなくなるとしたら?
牛肉、豚肉、鶏肉のうち、どれか一種類をこの先一生食べられなくなるとしたらどれを我慢しますか?
-
【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
【お題】 ・このサンタクロースは偽物だと気付いた理由とは?
-
C言語のポインタに直接アドレスを割り振りしたい
C言語・C++・C#
-
メモリをアドレスを直接指定して値を取得するには
C言語・C++・C#
-
指定したメモリアドレスの値の読み出し(自己改変コードの作成)
C言語・C++・C#
-
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
2重定義って??
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
関数の実体定義にヘッダファイ...
-
C++ クラスをメンバにもつクラ...
-
C++のfor文について
-
構造体を引数とする、クラス間...
-
C++のコンストラクタを宣言する...
-
inline
-
値を返り値に返すのと参照渡し...
-
C++でboolにintの値を代入する...
-
クラスのメンバ関数を別ファイ...
-
変数の型を定義しなかった場合...
-
64bit → 32bit型へのキャスト
-
waveout関数を使うと「○○は一度...
-
引数で argc argvが使用され...
-
スレッドのスケジューリングポ...
-
main.c:7:43: warning: implici...
-
LNK2019: 未解決の外部シンボル...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
C++のfor文について
-
2重定義って??
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
typedef enumの使い方を教えて...
-
C++でboolにintの値を代入する...
-
プログラムの中で別のmainを呼...
-
構造体の要素すべてに対する四...
-
変数の型を定義しなかった場合...
-
intとINTの違いは?
-
main.c:7:43: warning: implici...
-
【#define】 defineで定義した...
-
構造体の宣言でエラーが出ます。
-
関数の実体定義にヘッダファイ...
-
ハンドルされていない例外が発...
-
void func( void )について
-
エラー「invalid conversion fr...
-
sshdログの意味
-
C言語での方向キー入力判定
おすすめ情報