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

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

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

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

Q&A

解決済

3回答

1188閲覧

ポインタ構造体の中の数の出力

minmin231

総合スコア2

C

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

0グッド

0クリップ

投稿2021/12/15 15:11

前提・実現したいこと

プログラミング初心者です。
気になることがあり下記のようなプログラムを実行してみたのですが、プログラムが強制終了してしまいました。何が駄目なんでしょうか。

発生している問題・エラーメッセージ

該当のソースコード

include<stdio.h> struct Node{ int key; }; struct Node *T; int main(void){ printf("%d", T->key); return 0; }

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

jimbe

2021/12/15 16:17

T が何も指していないからです。
guest

回答3

0

ベストアンサー

この質問をする方にいうのもちょっと、という感もありますが、言っちゃいます。

便宜上「ポインタの指す先が"無い"」「どこも指していないポインタ」などといいます。プログラムのソースコードレベルの概念としてはそういうこともあるのですが、コンピュータ上で実際にプログラムが動くときには(値を持っていないint型変数、などというのがないのと同様に)ポインタは変数としてなんらかの値を持っています。ポインタが持っている値ですからそれはアドレスで、ポインタ経由のアクセスを指示されればC言語のプログラムは実際の動作として、そのアドレスにアクセスをします。値が0だろうとなんだろうと。
ここまでがC言語の動き(プログラムが「強制終了になる」なんて話は一切出ていないことに注意してください)。

で、ここからOSだとかハードウェアの話になります。
最近のOSはメモリ管理をしていて、メモリの領域毎にアクセスを見張っています。アプリケーションはOSに「申請」をして、もらった領域だけについて「読み出す」あるいは「読み書きできる」のですが、それ以外の領域をいじろうとすると、OSから規約違反ということでお叱りを受けます。そのお叱りが例えば「アクセス例外」とか「強制終了」。
あるいは、例えば奇数番地からの複数バイトアクセスは許されない、なんていうCPUもあって、そういうCPUでは奇数番地からのアクセスがあるとハードウェアとして割り込みが発生してプログラムの動作が中断したりもします。

これが無効なアドレスにアクセスすると強制終了する...の流れです。

決して「C言語が」強制終了させているわけではないことに注意。というのは、今回は初期化した値が確実に0だったのでOSが確実に検知できてキレイに強制終了になりましたが、そうでない場合もあるから。
C言語では「ローカル変数は意図的に初期化しない限り初期値不定(プログラムを実行してみるまで値が何になるか決まらない)」ということになっています。そういう条件下で生成したヘンな値を持ったポインタ、あるいは単に計算を間違えてヘンな値が入っていても同じことですが、これがたまたまOSから使用許可をもらっているアドレス値になっていて、そこにアクセスして他のソースコード上ではなんの関わりもない他の変数等を書き換えてしまうことはあり得るわけです。
そうなると、
・C言語そのものにはヘンなアドレスへのアクセスを止める仕組みはない
・OSも、許可を与えたアドレス範囲内のアクセスのミスは検知できない
ので、場合によっては「強制終了するわけでもないが、滅茶苦茶な動作を始める」などという結果になって影響が現れたりします。
(世の中には、OSのない環境で動くプロクラム、あるいはメモリ管理機能のないOSなんてのもあるので、そういう場合はもはや「命綱なし」であるとも言えるのですが)

C言語は「プログラムの動作は全てプログラマの責任」ということで、不当なアクセスの検証を放棄しています(かっこよく「プログラマの邪魔をしない」とか言ってはいますが、C言語ができた1970年代のコンピュータの能力にそこまで面倒を見る余裕はなかった、ということでもあるのでしょう)。
なので、「変なポインタ値になっちゃっても強制停止になるからわかるんだ」などと思ってしまわないようにしてください。一見ちゃんと動いているプログラムの奥底でじわじわと他のデータを破壊していて、ある日突然バグが発覚する...なんていうのはC言語ではよくあることです。

投稿2021/12/15 23:36

編集2021/12/15 23:39
thkana

総合スコア7703

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

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

minmin231

2021/12/16 00:29

詳しく説明していただきありがとうございました。
guest

0

struct Node *T;

Tという名前のNodeのアドレス変数(ポインタ)を定義してますが、実態(ナカミ)がどこにもありません
ポインタってのは、変数を指し示すもの、ですが、その肝心の変数がなく初期化もしていません

その実態のないアドレスでアクセスしていってるため、(幸運なことに)エラーが出てます

投稿2021/12/15 23:35

y_waiwai

総合スコア88042

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

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

0

何が駄目なんでしょうか。

ポインタはメモリのアドレスを指し示す変数です。
現在、そのアドレスが指し示されていない為にエラーになっています。
以下の説明が分かりやすいかも知れません。

■ 初心に戻り、C言語のポインタについて考える
https://qiita.com/developer-kikikaikai/items/0910c3c96e2164094449

以下は参考情報です。Visual C++ でデバッグ実行した結果になります。

イメージ説明

投稿2021/12/15 16:37

cx20

総合スコア4648

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問