アンパサンドを付けた場合のアドレスの違いについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
パクパク
記事: 23
登録日時: 7年前

アンパサンドを付けた場合のアドレスの違いについて

#1

投稿記事 by パクパク » 7年前

いつも回答ありがとうございます。

早速ですが、以下のコードにて、12行目の変数iにアンパサンドを付けた場合と付けない場合でアドレスに違いがあるのですが、これは変数用のアドレスと実体用のアドレスが異なる為でしょうか。ご回答お願い致します。

コード:

#include <stdio.h>

int main(void)
{
  int i, *p, **mp;

  p = &i;
  mp = &p;

  **mp = 10;

  printf("%p %p %p", &i, p, mp);

  return 0;
}

non
記事: 1097
登録日時: 9年前

Re: アンパサンドを付けた場合のアドレスの違いについて

#2

投稿記事 by non » 7年前

パクパク さんが書きました: 12行目の変数iにアンパサンドを付けた場合と付けない場合でアドレスに違いがあるのですが、
どこのアドレスが違って出力されるのですか?
ちなみに、iに&をつけないときの %p出力はアドレスが出ているのではなく、iの値10が16進数で出ます。
non

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: アンパサンドを付けた場合のアドレスの違いについて

#3

投稿記事 by softya(ソフト屋) » 7年前

厳密に言えば多くのPCの処理系は%pはアドレスを表示するのではなく、受け取った数値をアドレスとして解釈すると言う仕組みになっています。 [YuOさんに突っ込まれたところを修正。すいません書き方が悪かったです]なので、
printf("%p %p %p", i, p, mp);
とした場合はiの変数値がそのまま表示されます。

>変数用のアドレスと実体用のアドレス

どのようなものを想像されているか分かりませんが、違います。
仮想記憶の仕組みを除いてアドレスには2種類ありませんし、一般のプログラミングで仮想記憶を意識することはありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

パクパク
記事: 23
登録日時: 7年前

Re: アンパサンドを付けた場合のアドレスの違いについて

#4

投稿記事 by パクパク » 7年前

疑問が氷解しました。
お二方、素早い返信ありがとうございました。

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: アンパサンドを付けた場合のアドレスの違いについて

#5

投稿記事 by YuO » 7年前

解決されていますが……。

&iに対応する書式は%p,この書式が要求する物は「(void *型の)ポインタ」です。
%pに対してi,つまりはポインタでないものを渡した場合の動作は未定義動作となっています。
なので,標準出力への出力自体が保証されません。
ref) ISO/IEC 9899:1999 (以下IS) 7.19.6.1 The fprintf function ¶8, ¶9,IS 7.19.6.3 The printf function
# 細かく言うと,pointer to voidでないポインタを渡した場合も未定義動作 (IS 6.5.2.2 Function calls ¶6も参照) なので,void *へのキャストが必要。

さらに,%pの出力内容は処理系依存です。
fscanfの定義 (IS 7.19.6.2 The scanf function ¶12) より,異なるポインタを渡した場合に異なるシーケンスを返す必要がありますが,
それは例えば呼ばれる度にポインタを記録し,そのインデックスを%pの出力内容としても規格に合致します。
# 規格上,同一ポインタを%pに渡したときに同じシーケンスを生成する必要はないはず。
なので,%pは「同一の実行においてfscanf系で元に戻せるシーケンス」以上を想定しない方がよいです。

閉鎖

“C言語何でも質問掲示板” へ戻る