C言語の電卓におけるincludeについて

C言語の電卓におけるincludeについて質問です。

プログラミング言語C第2版 ANSI規格準拠
B.W.カーニハン・D.M.リッチー著

質問1.
4章にある電卓プログラムですが、getch.cがcalc.hをincludeしないのはなぜですか?
解説よろしくお願いします

calc.h
#difine NUMBER '0'

main.c
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"
#difine MAXOP 100

getop.c
#include <stdio.h>
#include <ctype.h>
#include "calc.h"

stack.c
#include <stdio.h>
#include "calc.h"
#difine MAXVAL 100

getch.c
#include <stdio.h>


質問2.
第4章までしか読んでいませんが、「関数で返さない値はゴミ(garbage)になる」と書いていました。

関数で返さない値は、関数から抜けると消えるものと思っていたので驚きました。
関数で返さない値の後処理はどうすればいいのですか?


質問3.
外部変数と静的変数の違いは?

―メモ―
局所変数 自動変数     main内の変数     int x;
                         static int x; 永久的なメモリが与えられることを意味する
外部変数          main外の変数     static int x;
静的変数          関数内の変数     static int x;
レジスタ変数        変数をレジスタに置く register int x;


以上、有識者の方、教えてくださいmm

このQ&Aに関連する最新のQ&A

A 回答 (10件)

>4章にある電卓プログラムですが、getch.cがcalc.hをincludeしないのはなぜですか?



手元にその書籍がないんですが、"getch.c"では"calc.h"で定義や宣言しているものを使っていないからでしょう。
それ以外の"main.c","getop.c","stack.c"は、NUMBERなどを使っているはず。

>関数で返さない値は、関数から抜けると消えるものと思っていたので驚きました。
>関数で返さない値の後処理はどうすればいいのですか?

スタック上にとられる、通常の変数の値なら、関数(というより、変数が宣言されたスコープ)を抜ければ、自動的に領域が開放されるので後処理は不要です。
しかし、malloc()や new などで動的に領域確保された変数の場合は、それぞれ free() や delete を明示的に呼ぶ後処理が必須です。
これらを忘れると、メモリリークを起こします。


>外部変数と静的変数の違いは?

>外部変数          main外の変数     static int x;
>静的変数          関数内の変数     static int x;

外部変数は通常、別なコンパイル単位("*.c"ファイルなど)からアクセスできるものを指します。
なので、staticは指定しません。
私なら、このように分類します

>局所変数 自動変数 関数内の変数  int x;
>     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
>外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
>ファイル静的変数  関数外の変数  static int x;
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 15:59

>書かなくてもいいけど書いた方がいいよと著者は言っています。


>ゴミになるから。

戻り値がある関数の場合、呼び出し元に対して「必ず」何らかの値を戻さねばなりません。
そうしなかった場合、その関数から呼び出し元が受け取る値は、文字どおり「ゴミ」です。

一方、戻り値がない関数の場合、最後の実行文を実行した後「だけで」呼び出し元に戻るのであれば、
return; はあってもいいし、なくてもいいです。
こちらの場合、ゴミなるものはいっさい出ません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

この質問は数日経ったので締め切らせていただきます。
ありがとうございましたmm

お礼日時:2009/05/19 16:40

>returnがなくてもreturnを明示的に書きなさい。

そしてreturn voidと書きなさい。

戻り値の型がvoidである(呼び出し元に何も返さない)関数では、
「return; を明示的に書かねばならない」ということはありません。
関数の途中で呼び出し元に戻るときは当然 return; が必要ですが、
関数の最後で呼び出し元に戻るときは return; を書いてもいいし、書かなくてもいいです。

また、return void; は正しくありません。やってみればわかります。
void は型名で、return int; などとは書けないのと同じです。
    • good
    • 0
この回答へのお礼

ありがとうございます。

return文がおかしいことがわかりました。
大変為になりました。

>return; を書いてもいいし、書かなくてもいいです。
書かなくてもいいけど書いた方がいいよと著者は言っています。
ゴミになるから。

いま6章です。
わかるようなわからないようなと言ったところです。
ということはわかってませんね・・・
多分、1回読んだだけではわからないのか。

ただ僕がアホなだけなのか。。

お礼日時:2009/05/18 16:51

質問1と質問3は、#6さんが既にご回答なさっている通りです。



質問2について、原文では以下のようになっています。

 The return statement is the mechanism for returning a value from the called function to its caller. Any 'expression'(任意の「式」) can follow return:

 return expression;

 The 'expression' will be converted to the return type of the function if necessary.
Parentheses are often used around the 'expression', but they are optional.

 The calling function is free to ignore the returned value.
 Furthermore, there need be no 'expression' after return; in that case, no value is returned to the caller.


 Control also returns to the caller with no value when execution "falls off the end" of the function by reaching the closing right brace.
 It is no illegal, but probably a sign of trouble, if a function returns a value from one place and no value from another.
 In any case, if a function fails to return a value, its "value" is certain to be garbage.

 一つの関数が、或る場所では返り値を返し、別の場所では返り値を返さない場合があったとしても、合法である、トラブルのサインにはなるだろうが。
 どんな場合にせよ、関数が返り値を返すことに失敗した場合、その返り値のもとになっている変数は、ゴミになる(不要な物として消滅する)。


「関数で返さない値は、関数から抜けると消えるもの」も、この場合の「ゴミ」と同義です。

>関数で返さない値の後処理はどうすればいいのですか?

何もしなくていいです。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2009/05/18 16:47

>#3さん


>外部変数は通常、別なコンパイル単位("*.c"ファイルなど)からアクセスできるものを指します。
>なので、staticは指定しません。

関数の外で定義する変数にstatic属性を付ける例はいくらでもあります。
#6さんの回答や、私の#4をお読みになって、認識を改められる方がよいです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 16:01

= 質問1 =


getch.c が calc.h を include していないのは、他の方も指摘している通り、getch.c 内では calc.h の内容を使用していないからでしょう。

ただ、calc.h には getch.c にある関数の宣言が書かれているので、include する方が好ましいように思います。include することにより、calc.h にある宣言と getch.c にある定義の内容が食い違ってしまう書き間違いをした場合にコンパイラがエラーを検出してくれるようになってミスに気づきやすくなるからです。

= 質問2 =
引用されている文は4.1節の後半にあるものだと思いますが、ここに書かれているのは関数内で単に return と書いた場合に関数の呼び出し側へどのような値が返されるのかという話で、その場合には「ゴミ」が返されるという説明に読めます。

この文は、関数内で使用した変数が破棄されるかどうかという話とは無関係だと思います。

= 質問3 =
外部変数とは、関数の外で定義された変数のことです。
静的変数とは、(定義が関数の外か中かは関係なく)「static」付きで定義された変数のことです。

外部変数は、変数を複数の関数から参照したい場合に使用します。
静的変数は、外部変数に対する場合と内部変数に対する場合で用途が異なります。
外部変数に対する静的変数は、その外部変数が定義されているファイル以外のファイルに書かれている関数からはその変数を参照できないようにしたい場合に使用します。
内部変数に対する静的変数は、内部変数の値を関数がreturnした後も保持し続けたい場合に使用します。
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 16:00

>#1さん


>静的変数と対比するなら、動的変数。

静的(static)変数と対比するのは、自動(automatic)変数です。
対比する点は、変数の寿命がどこで尽きるか、というところです。

一般的な用語としてならば、静的(static)と動的(dynamic)とを
対比させることに問題はありません。
しかし、C言語においてはそうではありませんね。
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 16:00

>#2さん


>静的変数は、ある関数内でのみアクセスできる変数

誤解があるようです。
static変数には、関数内部のstatic変数と関数外部のstatic変数とがあります。

関数内部のstatic変数は、関数内部のauto変数とは異なり、
その関数を抜けた後も寿命を保ちます。

関数外部のstatic変数は、その関数を含む翻訳単位内に属する他の関数からも等しくアクセスできます(ファイルスコープ)。
言い方を変えると、関数外部のstatic変数には、
その変数を定義した翻訳単位の外からは見えない、という特徴があります。
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 16:00

こんにちは。



>質問1
getch.c内で、calc.hで定義されている情報(プロトタイプやグローバル変数など)を参照する必要がないからだと思います。
getch.cの全文を見ていないので推測ですが。

>質問2
関数内部で使用した変数(=メモリ)は、関数を抜けるとそのままになります。malloc()などを用いて明示的に確保したのであれば、抜ける前にリソースの開放をする必要があります。(これを忘れることをメモリリークと呼びます。プログラマを悩ませるバグの1つです)
int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

>質問3
外部変数(=グローバル変数)は、あるプログラムコード上のどの関数からもアクセス(読み書き)できる変数です。
静的変数は、ある関数内でのみアクセスできる変数で、他の関数内で同名の変数を定義したとき同一のものとして処理され、その関数からもアクセスできるようになるものです。
他の関数内で呼び出さないのであれば、静的変数も自動変数と大差ありません(そうする意味もありませんし)
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 15:59

> 質問3.


> 外部変数と静的変数の違いは?
対比するものが、無意味です。
外部変数と対比するなら、ローカル変数。
静的変数と対比するなら、動的変数。

です。
    • good
    • 0
この回答へのお礼

ありがとうございます。
みなさまの意見を統括し、自分なりの回答が出ました。
また、間違っていたら教えてください。
数日したら締め切りたいと思いますので、誤りがありましたら、数日中にお願いします。

―質問1の回答―
getch.cがcal.hの内容を使用していないため。

―質問2の回答―
returnがなくてもreturnを明示的に書きなさい。そしてreturn voidと書きなさい。
そうしなければreturnが返す値はゴミです。

int型などは関数を抜けた後も残りますが、違うプログラムがロードされたときに上書きされますから、
後でロードされたプログラムがきちんと初期化処理をすれば動作しますので、開放しなくても大丈夫です。

malloc()や new などで動的に領域確保された変数を開放するのは当たり前。
それぞれ free() や delete を明示的に呼ぶ後処理が必須です。

int型も関数を抜けての残るが、同じ領域が使われるためきちんと動くわけですね。
ブロックから出ると値が無効になるって習ったのでやはりどちらにしろ驚きです。

―質問3の回答―
局所変数 自動変数 関数内の変数  int x;
     静的変数 関数内の変数  static int x; //永久的なメモリが与えられることを意味する
外部変数      関数外の変数  int x; //ヘッダファイルで extern int x; と宣言
ファイル静的変数  関数外の変数  static int x;

お礼日時:2009/05/17 15:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


人気Q&Aランキング