• ベストアンサー

戻り値について

プログラミング初心者です。 よろしくお願いします。 C++を使っています。 早速なのですが、以下にプログラムを記載します。 ◎1---------------------------------------- #include<stdio.h> main() { char ss[256]; gets(ss); puts(ss); } ---------------------------------------- ◎1を実行すると、「型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません」と表示されます。 参考書には、「戻り値のvoidがないと勝手に戻り値の関数をint型と解釈する。関数の宣言と定義が合わないとコンパイル時にエラーとなる」とあったのですが、 ◎2------------------------------------- #include<stdio.h> int main() { char ss[256]; gets(ss); puts(ss); } ------------------------------------- 以上の◎2だと、なぜ実行出来るかよくわかりません。 本当に初心者的な質問ですいませんが、教えていただけると嬉しいです。

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

  • ベストアンサー
回答No.4

>gets(ss);やputs(ss);という関数の戻り値がint型じゃないから、だめという感じですかね?? この件は「関数の中で呼んでるgetsやputsは無関係」ですよ。 以下のそれぞれの書き方で、コンパイラがどういう反応をするか、確かめましょう。 まず、以下の1~4を「拡張子を.cpp」にして、C++としてコンパイルしてみましょう。 ◎1 main() { } ◎2 int main() { } ◎3 main() { return 0; } ◎4 int main() { return 0; } 次に、上記の1~4を「拡張子を.c」にして、Cとしてコンパイルしてみましょう。 1、2の反応が「C++のとき」と「Cのとき」で違った筈です。 >◎1を実行すると、「型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません」と表示されます。 「mainの戻り値が何も書かれていないので、仮にint main()だと言う事にしますよ」と言っています。 >以上の◎2だと、なぜ実行出来るかよくわかりません。 C++では「intを返すmain関数の終りにreturn 0;って書いてなかったら、return 0;を勝手に付け足します」って言う「お約束」があるのです。 >visual studio 2005を使っているのですが、ソースファイル名の拡張子をC++の「.cpp」から「.c」とし、Cとして使うように変更すれば、◎1は動きました。ありがとうございます。 C++の場合、 main() { } と書くと、コンパイルする時に「型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません」という警告が出て、勝手に int main() { } だということにされます。C++では、書き忘れを足してくれるのです。 そして「intを返すmain関数の終りにreturn 0;って書いてなかったら、return 0;を勝手に付け足します」と言うお約束があるので、勝手に int main() { return 0; } だということにされます。C++では、書き忘れを足してくれるのです。 なので、Cとしてコンパイルしてしまうと、これらの書き忘れを足してくれなくなり、警告も出してくれなくなります。 つまり >拡張子をC++の「.cpp」から「.c」とし、Cとして使うように変更すれば、◎1は動きました。 は間違いです。 Cとしてコンパイルすると、見た目には「警告も出ず、コンパイル出来てしまう」ので、ちゃんと動くと思いがちですが「ちゃんと動いてはいない」のです。 コンパイラは「書き忘れを足してくれない」し「警告も出さない」ので、main関数から「変な値」を返したままになっています。 main関数から返される値は「プログラムが正常終了したか、異常終了したかを、プログラムを起動した人に返す役目」があります。 例えば「バッチファイル」で、◎1をCとしてコンパイルしたプログラムを呼び出した場合、バッチファイルで「正常終了したのか異常終了したのか判らない」って事が起きます。 ネットで「バッチファイル ERRORLEVEL」で検索してみて下さい。検索したページを見れば「◎1をCとしてコンパイルしたプログラムは、マトモに動作してない」って事が判ります。 以下、とっても重要。 ∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨ 「コンパイラが警告を出さなくなったからと言って、そのプログラムがマトモに動くとは限らない」 ∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧

muffler
質問者

お礼

前回のリダイレクト指示の時と同様、わかりやすくご指導いただき大変参考になりました。 C++はエラーを見逃さず、促してくれるものだとわかりました。 最後に書かれている言葉は、本当に大事だと思います。 ありがとうございます。 試しにコマンドプロンプトから、C++の◎1をやってみたら、実行出来てしまうのは、何故かなと思いました。

その他の回答 (3)

noname#208124
noname#208124
回答No.3

int mainに限りreturnせずに最後まで実行された場合return 0;とする、というのが最新のC/C++規格では規定されています

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

参考書は C について説明しています Cでは関数の戻り値の型を省略すると int と解釈されます お使いのコンパイラが不明ですがソースファイルの拡張子を .cpp から .c にすれば C としてコンパイルされるかもしれません。

muffler
質問者

お礼

visual studio 2005を使っているのですが、ソースファイル名の拡張子をC++の「.cpp」から「.c」とし、Cとして使うように変更すれば、◎1は動きました。ありがとうございます。 C++は何か複雑ですね。。

回答No.1

C++じゃなくって言語的にはCですよね? ところで、◎1だと……「戻り値のvoidがないと勝手に戻り値の関数をint型と解釈する。関数の宣言と定義が合わないとコンパイル時にエラーとなる」の例としては適切じゃないんですが……。つまり、ここで言う「戻り値」が何なのか、そして「関数の宣言」と「定義」がどの部分指してるのか分かりづらい、って事ですよね(しかも、main関数で戻り値ってvoidにするのって推奨されてない、とか思うんですけど)。 つまり、 #include<stdio.h> main() { char ss[256]; gets(ss); /*ここ*/ puts(ss); /*ここ*/ } は別に「戻り値」として機能してるわけじゃないんです。これらは値を特に戻してない、のです。 注:これちょっとややこしいんですが、元々、工学的には「値を戻す」プログラムを「関数」と呼び、「値を戻さない」プログラムを手続き(プロシージャ)と呼ぶんです。例えばPascalなんかはそれなりに分けています。 一方、Cは「全てを関数」と呼ぶんですが、要するにvoid型の戻り値を持つ関数、ってのは工学的に言うと「関数」ではなくって「手続き」なんです。 また、main関数はそもそも「関数」として設計されるべきで、これをvoid型宣言して「手続き」として定義するべきではありません(コンパイラによっては「許してます」が、推奨されている書き方じゃない、と思います)。そしてmainの「戻り値」ってのは数学的に何かの意味がある数値ではなく、単にOSに「プログラムが正常実行出来たよ」「出来なかったよ」と教えるため「だけ」に存在します。 正確には次のように書くべき、でしょうね。 #include<stdio.h> main() { char ss[256]; gets(ss); puts(ss); return 0;/*これが必要*/ } この「return 0;」ってのがmain関数での「戻り値」になります。◎1のケースですと元々「return 0;」が省略されている、と考えられるんです。 と言う事は◎2がどうして実行されるのか、分かると思います。◎2が示しているコードは「本来は」次のようなものです。 #include<stdio.h> int main() { char ss[256]; gets(ss); puts(ss); return 0;/*これが必要。型は「int」。*/ } return 0;がある、とすれば型はintなんで、main関数のint宣言、と一致しますね。本当はこれが「正しい」書き方で、コンパイラによってはmain関数でint宣言した時点で、return 0;が「本当はある」んだ、って解釈してくれるのかもしれません。 いずれにせよ、mainでvoid宣言、なんてのはしちゃあダメだと思いますよ。

muffler
質問者

お礼

gets(ss);やputs(ss);という関数の戻り値がint型じゃないから、だめという感じですかね?? ちなみに、 ----------------------- #include<stdio.h> main() { char ss[256]; gets(ss); puts(ss); return 0; } -------------------------- と書き直しても、やはり同じエラーが出ました。。 visual studio 2005を使っているのですが、ソースファイル名の拡張子をC++の「.cpp」から「.c」とし、Cとして使うように変更すれば、◎1は動きました。 main関数の戻り値や引数は複雑ですが、何となくですが理解できました。ありがとうございます。

関連するQ&A