offsetofマクロの定義
- 評価
- クリップ 0
- VIEW 2,535
#define offsetof(s, mem) (size_t)&(((s *)0) -> mem)
offsetofマクロの定義を見てみますと。
やっていることは、なんとな~~くは分かるのですが・・・・
(s *)これはなんです???
アロー演算子が出てきているので、ポインタですよね??
シンタックスシュガーですか?
(((s *)0) -> mem)
この部分の式について何をやっているのか詳しく教えてください。
[追記]
実験してみました。
struct d {
int j;
char g;
long r;
}a;
printf("%p, %p, ", &(a), &(a.g));
printf("%d\n", &(a.g) - &(a));
struct d *v = NULL;
// printf("%d", v ->j); segmentation fault
printf("&(v) = %p\n", &(v));
printf("&(v -> j) = %p\n", &(v -> j));
printf("&(v -> g) =%p\n", &(v -> g));
&(v) = 00C2FE5C
&(v -> j) = 00000000
&(v -> g) =00000004
こんな結果になりました。オフセットになっております。
struct d v;
printf("%p", v);
printf("%p", v.g);
結果は、
&(v) = 002EFED4
&(v.g) =002EFED8
ちゃんとアドレスが出てきます。
分からないのは、「ヌルポインタにしたときに、なんで、アドレスがオフセットに変化しているか・・・」
ということです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+2
(s *)
は、s *
型へのキャスト演算子です。
オフセットは、「メンバを指すアドレス」引く「構造体全体を指すアドレス」となりますが、0をポインタに読み替えることで、この後者を0にして、引き算を不要としています。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
このマクロを使用すれば、構造体「s」の中における要素「mem」のメモリ番地を知ることができます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
+1
これは見た目以上に複雑な問題です。とりあえず「C言語の範囲で」説明します。
(C++言語の範囲ではさらに複雑になるので、追加で質問がなければC言語だけの説明にとどめます。)
まず、マクロという機能の意味は御存知ですね? 使用箇所で機械的に展開されます。
例えば、
struct A {int a; int b;}
...
offsetof(struct A, b)
と書くと、最終行は
(size_t)&(((struct A*)0) -> b)
として翻訳されます。括弧が多いですが1つづつ考えていきます。
まず、(struct A*)0の部分は、struct A型へのヌルポインタを作り出しています(0をポインタにキャストするとヌルポインタになる)。
次に、そのポインタを利用してメンバbにアクセスしています。構造体はヌルポインタなのに、そのメンバにアクセスするなんて物騒! そう思えるかもしれませんが、「実際にその値を利用しようとしない限り」そのようなアクセスも許容されています。今回はその外側の&記号でアドレスを求めているだけなので、bの値は利用しません。実際にアクセスできなくても、アドレスは計算できるのです。
最後に、そのアドレスに基づくポインタをsize_t型にキャストしています。ポインタから整数へのキャストは見慣れないかもしれませんが、そのポインタの値が「ヌルポインタから」どれだけ離れているかの値が、キャスト後の結果となります。結果、bのオフセットが計算されます。最初のヌルポインタ作成は、起点をヌルポインタにすることで、実体のある構造体を利用する場合に必要となる調整を省いているわけです。
以上、maisumakunさんの説明を小難しく解説しました。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/18 22:36
(* s)こうではないのですか??
0という数字をキャストしているのは初めて見かけたんですが・・・