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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

C++

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

Q&A

解決済

7回答

2883閲覧

C++ ポインタについて

saito.kaz

総合スコア76

C

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

C++

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

0グッド

0クリップ

投稿2016/03/31 11:16

編集2016/03/31 11:31

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

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

(*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/ツール等のバージョンなど)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答7

0

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

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

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

投稿2016/03/31 12:02

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:42

ありがとうございます。
guest

0

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

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

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

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

投稿2016/04/03 03:03

編集2016/04/03 03:06
aloha001

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

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

投稿2016/03/31 13:00

編集2016/03/31 13:05
nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:40

ありがとうございます。
guest

0

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

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

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

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

投稿2016/03/31 12:58

nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:40

ありがとうございます。
guest

0

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

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

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

C

1printf("%u", p) 2 3

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

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

投稿2016/03/31 12:22

kutsulog

総合スコア985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:41

ありがとうございます。
guest

0

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

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

C++

1p = &a;

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

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

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

投稿2016/03/31 12:18

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:41

ありがとうございます。
guest

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/03/31 12:11

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/04/01 08:42

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問