こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

戻り値について

プログラミング初心者です。
よろしくお願いします。
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だと、なぜ実行出来るかよくわかりません。
本当に初心者的な質問ですいませんが、教えていただけると嬉しいです。

投稿日時 - 2009-02-01 14:59:05

QNo.4680004

困ってます

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

>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としてコンパイルしたプログラムは、マトモに動作してない」って事が判ります。

以下、とっても重要。

∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨
「コンパイラが警告を出さなくなったからと言って、そのプログラムがマトモに動くとは限らない」
∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧

投稿日時 - 2009-02-02 12:36:51

お礼

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

投稿日時 - 2009-02-02 16:14:50

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

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

投稿日時 - 2009-02-01 22:14:10

ANo.2

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

投稿日時 - 2009-02-01 18:51:23

お礼

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

投稿日時 - 2009-02-01 21:23:32

ANo.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宣言、なんてのはしちゃあダメだと思いますよ。

投稿日時 - 2009-02-01 17:17:31

お礼

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関数の戻り値や引数は複雑ですが、何となくですが理解できました。ありがとうございます。

投稿日時 - 2009-02-01 21:21:22

あなたにオススメの質問