• ベストアンサー

C言語 main関数とsum関数の記述順について

はじめまして。 【苦しんで覚えるC言語】(Web版)でC言語を学んでいる初学者です。 【第1部:C言語基礎編】>【関数の作り方】>【自作関数を作る】の部分(http://9cguide.appspot.com/11-01.html#S2)でつまづいています。 下記のような、1から100までの数字の合計を表示するプログラムが例題として取り上げられています。 しかし、ここが理解できないので、次の【プロトタイプ宣言】に進めずにいます。 例題1  sum関数をmain関数の後に記述した場合(プログラムが実行されない)。 #include <stdio.h> int main(void) { return 0; } int sum(void) { printf("%d\n",(1 + 100) * 100 / 2); return 0; } 例題2  sum関数をmain関数の先に記述した場合(プログラムが実行される)。 #include <stdio.h> int sum(void) { printf("%d\n",(1 + 100) * 100 / 2); return 0; } int main(void) { return 0; } 例題1の場合、【まずmain関数を作り、次にsum関数を作りました。この場合、main関数を解析している段階では、sum関数は発見されておらず、従って、main関数の中では、sum関数を使うことは出来なくなってしまいます。】との説明がありますが理解できません。 コンパイラがどのような順番でプログラムを処理しているか理解できていないので分からないのだと思います。 例題1の場合と例題2の場合の両方について、コンパイラがどのような順番でプログラムを処理しているのかを具体的に教えてください。 どうかよろしくお願い致します。

  • 501xx
  • お礼率90% (398/439)

質問者が選んだベストアンサー

  • ベストアンサー
  • foomufoomu
  • ベストアンサー率36% (1018/2761)
回答No.4

たぶん、この例のmain()は int main(void) { sum(); return 0; } の間違いなのでしょうか。質問に書いてある通りでは、なにもしない関数になってしまいますから。 で、質問の答えですが、 「C言語では、main()は最後に書くのがルールです。」 の一言で済ませてしまってもよかったのですが、このサイトでは、もう少しそれらしい説明をしているのでしょう。 Cコンパイラは、それほど何度もパスを繰り返していません。なので、 「使う前に定義を書かないといけない」 というのが原則になっています。main() の中で使う前に、sum()の定義が必要なのです。 本気で勉強するなら、サイトでなく、本を買ったほうがよいですよ。

501xx
質問者

お礼

早速ご回答いただき、ありがとうございました。 例題が間違っており、すみませんでした(例題1・例題2ともに実行されないプログラムを載せてしまいました)。 また、関連する新しい疑問も出てきました。 頭を整理してから再度質問をし直します。

その他の回答 (4)

  • kngj1740
  • ベストアンサー率18% (197/1052)
回答No.5

これはC言語の仕様です。使用する変数や関数は先に定義または宣言する必要があります。コンパイルを少しでも早くするため(今から考えると当時のミニコンは遅かった)構文解析を1Passにしたのだと思います。 アセンブラ言語は普通2Passで解析します。後から出てきたシンボルがUndefineになる事はありません。 コンパイラ言語の構文解析は先頭から順に行います。解析結果はグラフ/ツリーのような形で表現されるらしいです。

501xx
質問者

お礼

早速ご回答いただき、ありがとうございました。 例題が間違っており、すみませんでした(例題1・例題2ともに何も実行しないプログラムを載せてしまいました)。 また、関連する新しい疑問も出てきました。 頭を整理してから再度質問をし直します。

回答No.3

まず、ここで書かれた例ではsum()をどこからも呼び出されていないのでどちらでも実行されません。 >main関数を解析している段階では、sum関数は発見されておらず、従って、main関数の中では、sum関数を使うことは出来なくなってしまいます。 この解説は間違い、後述の関数を使用出来ないのはCの言語仕様です。(出来ないと決めているから出来ない) コンパイラは頭から逐一翻訳していくのではありません。 コンパイラによって違いますが通常は数回から十数回のパスをへてオブジェクトファイルを出力します。 具体的にコンパイラがどのような解析をしているかは簡単には書けませんから専門書を参照してください。 なぜそのような仕様になっているかですが恐らくCの開発当時のコンピュータの演算能力や使用料の低減のために人間への負担を増やすことで少しでもコンパイラを簡易なものにするためでしょう。

501xx
質問者

お礼

早速ご回答いただき、ありがとうございました。 例題が間違っており、すみませんでした(例題1・例題2ともに実行されないプログラムを載せてしまいました)。 また、関連する新しい疑問も出てきました。 頭を整理してから再度質問をし直します。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

例題があまり良くないですねぇ。 >コンパイラがどのような順番でプログラムを処理しているのか プログラムを処理…ではなく、構文解析…というべきでしょうかね。 とりあえず、プリプロセスで疑似命令とか処理して1つのファイルとして、先頭から構文解析を進めているハズです。 ちなみに、例題1も例題2もsum()はコールされていませんからどっちも「実質なにもしないmain()」が実行されるだけ…ですよ。 どっちもmain()が int main(void) {  sum();  return 0; } だった場合、 例題1だとsum()の情報(引数の数や型、戻り値の型などの情報)が無い為、コンパイルエラーか警告となります。 # そういう場合の規定があった…かと。(引数、戻り値もint型とする…でしたかね) 例題2だとmain()からsum()をコールする時にはsum()の情報は解釈済みですのでコンパイルエラーや警告になることはありません。 # もちろん、正しく使っている場合に限りますが。 つまり、呼び出す前に呼び出し先の情報があればいい。 ということになります。 main()からfunc1()をコールしているからfunc1()をmain()より前に書けばいい。 func1()からfunc2()とfunc3()とfunc4()をコールしているからfunc1()の前にfunc2()とfunc3()とfunc4()をfunc1()より前に……とかやっていけば万事解決です。 そういう依存関係を考慮してソースを書く必要がある。ってことですね。 依存関係の結果入れ子になったらどうしましょうか。 func2()からfunc3()とfunc4()をコールしている。func3()からはfunc4()をコールしている。func4()からは条件によってはfunc3()をコールすることもある。 さて、どうしましょう? そんな依存関係も把握して書かないといけないなんて面倒ですね……。 ってことでプロトタイプ宣言ってものがあるんです。

501xx
質問者

お礼

早速ご回答いただき、ありがとうございました。 例題が間違っており、すみませんでした(例題1・例題2ともに実行されないプログラムを載せてしまいました)。 また、関連する新しい疑問も出てきました。 頭を整理してから再度質問をし直します。

  • ok-kaneto
  • ベストアンサー率39% (1798/4531)
回答No.1

先頭から順に解析しています。 例えば、変数で考えてみます。 main関数の中で int main(void) { i++; int i; } こうだと、エラーが出ます。変数の定義の前に変数を使用しているからです。 この場合、使用する前に必ず変数を定義する必要があります。 int main(void) { int i; i++; } 同様に、関数も定義するまえに使用してはいけないのです。ですからmainの前にプロトタイプ宣言するか、実態そのものを定義しておくか、プリプロセッサ(#include)で読み込んでおくかの必要があります。

501xx
質問者

お礼

早速ご回答いただき、ありがとうございました。 例題が間違っており、すみませんでした(例題1・例題2ともに実行されないプログラムを載せてしまいました)。 また、関連する新しい疑問も出てきました。 頭を整理してから再度質問をし直します。

関連するQ&A

  •  現在、私はC言語を学んでいます。

     現在、私はC言語を学んでいます。  プログラミングの初期の初期の問題なんですが、 「Hello World」という有名なプログラムがありますよね? それについての質問です。 #include<stdio.h> main() { printf("Hello World"); return 0; } も #include<stdio.h> main(void) { printf("Hello World"); return 0; } も #include<stdio.h> int main() { printf("Hello World"); } もちゃんと表示できます。 ここで質問です。 int main(void) int main() main() main(void) はどう違うんですか? あと、 return 0; はあっても無くてもいいようなんですが どういう意味があるんでしょうか?

  • Re: Vista c言語でのエラー

    直前の質問だったのですが、どうやらプログラムが壊れているみたいなんです。 #include <stdio.h> int main(void) { int sum,, no ; printf("整数を入力してください: "); scanf("%d", sum); printf("%d\n", sum); return (0); } と、とても簡単なプログラムに変えてみると、 整数を入力してください: 25 [Enter] 2147348480 となりました。また int sum, no; と変数を二個にすると前記のエラーが起こりました。 そのほかのプログラムを実行しても同じ結果でした。 コンパイラがおかしくなっちゃったんでしょうか?

  • C言語初心者です。

    C言語初心者です。 1^2-2^2+3^3-4^2…+99^2-100^2の値を求めるプログラムを作成したいのですが上手くいきません。 どこが足りないのですか? #include <stdio.h> int main(void) { printf("%d", 1^2 - 2^2 + 3^2 - 4^2 … + 99^2 - 100^2); return (0); } よろしくお願いします。

  • C言語 勉強始めた所で、まだ良く解りません、教えてください!

    C言語 勉強始めた所で、まだ良く解りません、教えてください! このプログラムを実行すると、5,5と表示されると思うのですが? /*****************************************************************************/ #include <stdio.h> int average( int *data, int count ) { int i, sum=0; for( i=0; i<count; i++ ) sum+=data[i]; return sum/count; } int main(void) { int numbers [] = { 2, 3, 5, 7, 9, 11, 13, 15, 17,19 }; printf("%d\n",average(numbers,5)); return 0; } /*******************************************************************************/ 5、だけしか表示されません、これでよいのでしょうか?

  • c言語で平均をだす

    #include<stdio.h> int main(void) { int num; int sum; printf("テストの点数を入力してください。\n"); do{ scanf("%d",&num); sum+=num; }while(num); printf("テストの合計点は%dです\n",sum); return 0; } テストの平均点をだすプログラムを作りたいのですが、合計を出すまではわかったのですが、ここから、平均を出すようにするにはどうすればよいですか。

  • C言語の代入についての質問です

    C言語の代入についての質問です 下のプログラムを見て下さい #include<stdio.h> int x[2]; x[0] = x[1] = 1; int main(void) { for(int i = 0 ; i < 2 ; i++) printf("%d",x[i]); putchar('\n'); return 0 ; } このプログラムをコンパイラすると3行目の代入にエラーが出されます (当たり前ですがmainの中に3行目の代入文を入れると上手くいきます) まぁそれがなぜかというのが知りたいのですが、 それはC言語をつくった人が決めたことなのでしょうか? ちなみに異なる実行環境でやってみたらどれも駄目だったので これが上手くいくことはない?のだと思います そういうもんなのだったら、そういうものだと理解しますが もし理由を知っている方がいらっしゃったら教えて下さい

  • 現在、C言語を習っています。

    現在、C言語を習っています。 今、関数を勉強しているんですがわからない文があるので正解の文を教えてください。 #include <stdio.h> int main (void) { int a=123; doubke b=4.5; printf("%d\n○○" ,a,b); return 0; } ○に入る言語や文が間違っていたら教えてください。

  • C言語プログラミングについて

    #include <stdio.h> int main(void) { printf("hello,world\n"); } □■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■ #include <stdio.h> int main(void) { printf("hello"); printf(",world"); printf("\n"); } 上の2つのプログラムをコンパイルするとどのような違いが生じるんですか??printfってどんな働きをするんですか?

  • C言語で分からないところがあるのですが・・・

    すみません。C言語で分からないところがあったので来ました。 ユーザから数字を任意の数だけ受け取って、その数字とその和を表示するプログラムです。atoiなる関数、そしてコマンドライン引数というのを使って考えてみた結果を下に書きましたので、どなたか修正してください。お願いします。 実行結果(のイメージ図) 20 39 4 sum 20 39 4 63 途中までのソースコードです。 #include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc,char *argv[]) { int sum; int n,i; printf("How many numbers INPUT?: "); scanf("%d", &n); for(i = 0; i <= n; i++){ atoi(argv[i]); } sum = printf("%d",sum); return 0; }

  • C言語

    最近C言語を始めたばかりなのですが、コンパイラをしたあと、オブジェクトファイルをexeしようとすると、エラーがでます。 そのエラーとは ”問題が発生したため、error.exe を終了します。 ご不便をおかけして申し訳ありません。この問題を Microsoft に報告してください。”です。 どなたかわかる方教えてください。 以下が、問題のプログラムです。 #include <stdio.h> int main(void) { int na; puts("身長を入力してください。"); printf("身長:"); scanf("%d",&na); printf("標準体重は[%.1f]です。%n", (double)(na - 100) * 0.9); return(0); }

専門家に質問してみよう