質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • C

    4638questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4501questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

C++ ポインタについて

解決済

回答 7

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 602

TAKAYUKI_MIWA

score 64

前提・実現したいこと

下記のコードはコンパイルに成功いたしましたが、一つ疑問になっていることがあります。

通常、ポインタの場合、アドレス値を出力するには、&を使う必要があると思いますが、下記の疑問があります。

(*1)についてですが、通常メモリは&をつけて表示すると思いますが、変な値が出力しましたがこれは、なぜでしょか。
(*2)と*(3)ですが、出力結果が両方とも0となりました。前者はポインタで何の指していないので、0。しかし後者は(1)と比較しても0になる理由が分かりません。

これはなぜでしょうか。

ソースコード

using namespace std;
int main(void){
    // Here your code !
    int a, b;
int * p;
int * Q;
a = 100;
p = & a;


printf( "%d\n", * p ); // 100
printf( "%d\n",  p ); // -1711247084 (*1)
printf( "%d\n", * Q );  // (*2)
printf( "%d\n",  Q ); // (*3) 
}

補足情報(言語/FW/ツール等のバージョンなど)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 7

+1

*1ですが、これはポインタ自体の値を出力しています。一般にはメモリのアドレスをそのまま流用しています。ふつう値自体を表示する必要はないですが、配列へのアクセスも内部的にはポインタの値の加減算です。

*2や*3ですが、こんなコードは書いてはいけません。関数内で宣言した変数は「自動変数」といいますが、デフォルトで何が入っているかは、誰も何も保証してくれません。ということで、そのようなポインタで*Qと参照してしまえば、何が起きるかわかりません(正式には「未定義の動作」といいます)。

未定義の動作は「まったく何も保証されない」ので、何事もなく適当な値を返しても、でたらめな結果を返しても、プログラムがOSを巻き込んでクラッシュしても、鼻から悪魔が飛び出そうとも、まったく問題ない、ということになってしまいます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:42

    ありがとうございます。

    キャンセル

checkベストアンサー

0

こんにちは。

(*1)についてですが、通常メモリは&をつけて表示すると思いますが、変な値が出力しましたがこれは、なぜでしょか。 

%dで出力しているため、pに設定されているアドレス(の一部)が10進数で表示されています。
C++のostreamを使うと、ほとんどのケースで適切に表示してくれるので、楽ですよ。
私なら、std::cout << p << "\n";で出力します。

(*2)と*(3)ですが、出力結果が両方とも0となりました。前者はポインタで何の指していないので、0。しかし後者は(1)と比較しても0になる理由が分かりません。

Qは初期化していないので、そこに設定されているアドレス値は不定です。お使いのコンパイラがたまたま未初期化変数を0クリアしてくれ、かつ、アドレス0番地に付近には0を入れるのだろうと思います。かなり珍しい動作です。コンパイラは何をお使いでしょうか?


【蛇足ですが】
C言語の標準ライブラリは多数の問題を抱えています。実用プログラムで適切に使うには非常に繊細な注意力と標準ライブラリの動作に関する深い深い知識を必要とします。
C++言語の標準ライブラリの場合、それに比べると落とし穴は少ないです。
C言語ではなくC++として学習されているのでしたら、C++の標準ライブラリにある機能はなるべくC++側を使うことをお勧めします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:42

    ありがとうございます。

    キャンセル

0

(*1)についてですが、通常メモリは&をつけて表示すると思いますが、変な値が出力しましたがこれは、なぜでしょか。 

これは変数aのアドレスです。

p = &a;


でpにaのアドレスを代入していますのでその値が表示されます。
アドレスですのでマイナスの値は不自然ですが、%dではなく%xで表示させると0x9A007114辺りの値になると思います。

(*2)と*(3)ですが、出力結果が両方とも0となりました。前者はポインタで何の指していないので、0。しかし後者は(1)と比較しても0になる理由が分かりません。

変数Qについては初期化も何もしていないので、不定値であってもおかしくないですが、コンパイラが親切に0を入れてくれているのだと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:41

    ありがとうございます。

    キャンセル

0

(*1)についてですが、通常メモリは&をつけて表示すると思いますが、変な値が出力しましたがこれは、なぜでしょか。  

メモリの番地を符号付整数で出力しているから
符号付整数の最大値を超えてマイナスになっています

次のように書けば符号なし整数で出力してくれます

printf("%u", p)

(*2)と*(3)ですが、出力結果が両方とも0となりました。前者はポインタで何の指していないので、0。しかし後者は(1)と比較しても0になる理由が分かりません。 

コンパイラが勝手に0で初期化してくれているので0が出ています
この動作は規定されている動作ではないため
別のコンパイラでコンパイルして実行すると
そのときたまたま使用するアドレスとたまたまそのアドレスに入っているデータを出力します

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:41

    ありがとうございます。

    キャンセル

0

(*1)
「変な値」とはどういうことでしょう?
どんな値ならOKで、どんな値はダメなのでしょう?普通はポインタの値の正誤を判定することはありません。表示された値がポインタの値です。
但し、組み込みのソフトでは、ポインタの値の範囲が決められるので、値の正誤を判定することはあります。

(*2)
自動変数Qに値を設定していないので、何が入っているかわかりません。ですからどのような値が表示されても不思議ではありません。

(*3)
どこを示しているか判らないポインタが示す先を表示しようとするので、やはり何が表示されても不思議ではありません。

(*2)、(*3)が0と表示されたのは、タマタマ です。
「何も示していないポインタは0」と言うわけではありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:40

    ありがとうございます。

    キャンセル

0

重複したので削除しました

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/01 17:40

    ありがとうございます。

    キャンセル

0

1 のケースは、ポインタ値を表示するためのリテラルがあります。%pを使いましょう。

2と3のケースは、他の方も答えていましたが、不定でありかつ、危険です。
使用しないポインタ変数は宣言してはならないというのは、大事なCの作法です。

少しメモリとCの文法の処理の基本なことですが。(アセンブラを学ぶと簡単に理解できます)
Auto変数は、スタックエリアに積み込まれます=int型ならば、sizeof(INT)バイトほど確保されます。
このとき、スタックエリアもメモリの一部で、そのブログラムで確保されるメモリエリアのどこに配置されるかはわかりません。よってたまたまそのエリアの内容が0だっただけです。
0が安心できるのは実数型のときだけです。ポインタで0番地にアクセスした場合、殆どの場合はそのPCは再起動されたり、動作が不定になるなどの危険をはらんでいます。
よって、使用しないポインタ変数は、宣言すべきではないのです。予備する場合は、安全な変数のポインタあたりを初期値として格納しておくなど必要です。

今、Udemyで日本語のプログラミング系講座(動画)がありますね。Cの講座もあるので、利用されるといいかもしれません。日本ではベネッセが運営しているそうです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4638questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    4501questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。