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

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

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

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

Q&A

解決済

2回答

5935閲覧

『関数内部で別の関数は定義できない』というのは本当でしょうか。

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

2グッド

1クリップ

投稿2017/11/26 07:55

編集2017/11/26 07:56

#はじめに
本にある記述が果たして正しいのかということが気になりました。
「Yahoo!知恵袋」などにも同じような質問はありましたが,満足する答えが得られませんでしたので,こちらで質問いたします。

#気になった本の記述
『やさしく学べるC言語入門[第2版]ー基礎から数値計算入門までー(皆本晃弥 著)』に複数の気になる記述がありました。
Amazon:やさしく学べるC言語入門[第2版]ー基礎から数値計算入門までー

###1. 「6.1関数の形式とmain関数」に次のような記述があります。

図6.1を見ると分かるように関数を利用するとプログラム全体の構造が見やすくなります.このように,プログラムの構造が見やすいのは,関数内部で別の関数を呼び出してはいますが,定義はしていないからです.そのため,C言語ではそのようなことを認めてはいません。

〈重要ポイント!〉

関数内部で別の関数は定義できない.

###2. 「6.4値渡しと参照渡し」に次のような記述があります。

このように値を返さない関数のことをvoid型関数と呼ぶときがあります。なお,void型関数は値を返さないのでプログラム6.2にあるようにreturn文を書いてはいけません。

c

1//プログラム6.2 2//値渡しだと値が変わらない例を示すプログラム 3#include<stdio.h> 4 5void swap(double x, double y); 6int main(void){ 7 double a=1.5, b=3.6; 8 //中略 9 return 0; 10} 11 12void swap(double x, double y){ 13 double tmp; 14 tmp = x; 15 x = y; 16 y = tmp; /*void型関数なので返り値はない*/ 17}

//コメント形式のコメントは私が追加でかいたもので,/* コメント */形式は本に記されているコメントです。)

#テストしたソースコード
###1.「6.1関数の形式とmain関数」について
GCCで次のコードをコンパイルしましたところ,何のエラーも起きませんでした。(GCCバージョン: 4.9.3)

C

1#include<stdio.h> 2main(){ 3 int sum(int c, int d){ 4 return c+d; 5 } 6 printf("%d\n",sum(5,2)); 7}

実行結果は当然のことながら,

> .\a.exe 7

でした。
また,g++ では,

>g++ .\sono1.c .\sono1.c: In function 'int main()': .\sono1.c:4:23: error: a function-definition is not allowed here before '{' token int sum(int c, int d){ ^ .\sono1.c:7:23: error: 'sum' was not declared in this scope printf("%d\n",sum(5,2));

とコンパイルエラーになりました 。

###2.「6.4値渡しと参照渡し」について
書いてはいけないというのは誤りな気がします。たとえば,下記のコードのように,途中で無理やりreturnしたい場合などがあると思うからです。(この関数に何の意味がないですが・・・)

c

1void print_difference(int a,int b){ 2 if(b>a){ return; } 3 printf("%d",a-b); 4}

#質問事項

  • コンパイラ,本のどちらが誤りなのでしょうか。
  • JIS・ISOなどでの規定はどのようになっているでしょうか。

よろしくお願いいたします。

LouiS0616, KSwordOfHaste👍を押しています

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

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

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

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

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

guest

回答2

0

C標準では関数の中で関数を定義できない規定になっていることは間違いありません。

GCCで次のコードをコンパイルしましたところ,何のエラーも起きませんでした。(GCCバージョン: 4.9.3)

それは「関数内関数」というgcc独自の拡張機能によるものです。当然のことながら利便性を考えてその機能を付け足したのであって「誤って付いちゃった」わけではありません。移植性(別の環境での利用)を考慮するなら、そのような独自機能は使わない方が無難です。

それと、main関数はintを外したからといってvoidにはなっていません。C言語では関数の型を省略するとintとみなされます。ですので、当然returnで値を返せます。

また,g++ では,
~中略~
とコンパイルエラーになりました 。

g++では関数内関数は使えないのでエラーになります。

書いてはいけないというのは誤りな気がします。

件の本を読んでいないので実際に何と書かれているのかは判りませんが、「値を返すreturn文を書いてはいけない」ということではないでしょうか。もし誤解されるような表現なら、それは本の表現上の誤りと言えます。

投稿2017/11/26 08:47

catsforepaw

総合スコア5938

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

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

0

ベストアンサー

こんにちは。

どうも gcc は関数内で関数を定義できる独自の拡張がされているようです。
clangではコンパイルできません。

C言語の標準規格上は関数内関数は定義できない筈です。
ただ各コンパイラが必ずしも標準規格を厳密に守っているとは限りません。
各コンパイラは概ね標準規格に準拠するよう努力しているようですが、各コンパイラ・ベンダーにはそれぞれ主義主張や優先順位がありますから。

プログラム6.2にあるようにreturn文を書いてはいけません。

この文言が編集ミスっぽく感じます。
「プログラム6.2にあるように(戻り値付きで)return文を書いてはいけません」が書きたかったことではないかと予想します。

投稿2017/11/26 08:40

Chironian

総合スコア23272

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

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

退会済みユーザー

退会済みユーザー

2017/11/26 08:45

なるほど!コンパイラが拡張するということがあるのですね…! また,`return`文についても納得しました。すばやい回答をありがとうございます_(._.)_
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問