C ++での関数宣言の後にセミコロン( ';')は必要ありませんか?


174

最近、中間プログラミングテストを受けましたが、私が間違った質問の1つは次のとおりです。

関数宣言の後にセミコロン( ';')は必要ありません。

正しいか間違っているか。

私は「false」を選択しました(そして、私が狂っているように感じるので私が間違っている場合は修正してください)、関数宣言は、定義の前(コードの先頭)に書き込むものなので、コンパイラーは関数を認識します呼び出す前に呼び出します。関数定義は、関数全体を構成するものです。

つまり、

宣言:

int func();

定義:

int func() {
  return 1;
}

これに対する答えは間違っているべきではありませんか?


41
定義も宣言です。しかし、私はあなたの答えは正しかったと思います。

216
これはトリッキーな問題であり、上手にプログラムするための誰の能力にも影響を与えません。
phonetagger

40
私はいつも疑問を見つけます。その結果、ダブルネガティブになり、混乱します。私の考えでは、そのような質問は学生をつまずかせるように設計されています。「関数の宣言の後にはセミコロン( ';')が常に必要です。TrueまたはFalse。」のように質問を作成できないのはなぜですか?:/
AlgirdasPreidžius19年

18
@phonetaggerこのすべての混乱は、質問がどれほどひどい言葉で書かれているかを示しています。
フランソワアンドリュー

34
HanlonのRazorは、テストの作成者が「宣言」と「定義」を混同したことを示唆しています。
Sneftel

回答:


161

関数の宣言と定義を1つのステップで行う場合があります。つまり、関数の定義を宣言する場所に含める場合などです。したがって、技術的にはtrueが正しいと思います。しかし、質問はあなたがしたのと同じように答えるような言葉で書かれています。


10
私はあなたが与えた理由のためにtrueは正しくないと主張します。セミコロンが必要な場合がある場合、それは偽(または真ではない)です。Trueは私にとって絶対的なものです。それが必要な明確なケースがある場合は、trueとは言えません。
私は

16
@IFunball良い議論。愚かな自然言語。文;として読み取ることができ、「セミコロン( 『』)関数宣言の後は必要ありません」「セミコロン( 『;』)ではありません(これまでの)関数宣言の後に必要に応じて」またはセミコロン(」として『;』 )は(常に)関数宣言の後には必要ありません。ステートメントを真または偽として修飾するかどうかは、解釈の選択にかかっています。厳密に話された質問は不明確であるため、明確な答えはありません。
ピーター-モニカを復活させる

6
@IFunballそれは、「宣言」は、それ以上の文脈も、私たちが言語弁護士であるという記述もない、「非定義的な宣言」を意味すると一般に理解されているからです。質問は不公平でした。
にオービットで軽量レース

2
テスト対象のコンテンツを知っている人にとって不明確な試験問題は、バグが含まれています。
Nat

2
未定義の動作句を英語に追加する必要があるようです
Nick Mertin

147

「定義は宣言でもある」ことに加えて、以下は正当なC ++です。

int f(), g();

これは2つの関数とfを宣言します。g両方とも引数なしで、戻り値の型がintですが、の定義のf後に(すぐに)セミコロンが続きません。同様に、これは合法です:

int f(), i = 42;

ただし、これらのケースではセミコロンを完全に省略することは実際には許可されていないため、セミコロンを付けずに宣言の例としてどちらかを使用した場合は、多少意外です。実際、以下は違法です。

void *p, f() {}

(単なる)関数宣言以外の関数定義は同じに他の宣言または定義と組み合わせることができないタイプ指定子。(これが合法であれば、a void *pとの両方を定義しますvoid f() {}。)

いずれにせよ、これは、中間のプログラミングテストに含めるべきではない「ごちゃごちゃ」タイプの質問のようです。

(ところで、実際にのようなコードを記述しないでくださいint f(), i = 42;。)


2
typedefを使用して関数の型を定義し、それを利用して一度に多くの関数を宣言することも可能typedef int fooProc(int); fooProc a,b.c.d.e;です。たとえば、フロッピードライブベースのコンパイラの標準ヘッダーがそれを元に戻さなかった理由がわかりませんヘッダーファイルをかなり小さくして、処理を高速化できると思っていたからです。
スーパーキャット

また、int f(int(&g)(),int(*h)()){return g()+h();}これには3つの関数宣言があることを考慮してください。
デビッドハメン

1
@DavidHammen:は、以外の関数を厳密に宣言していませんint f(stuff)。偶関数の範囲で、g型の自動変数である関数を参照し、hある関数へのポインタ
Peter Cordes

83

他の回答とコメントは、これが恐ろしい、誤解を招く、下手に書かれた質問である多くの方法のいくつかを呼び起こします。しかし、他の誰もまだ特定していない別の問題があります。質問は:

関数宣言の後にセミコロン( ';')は必要ありません。正しいか間違っているか。

では、関数宣言を見てみましょう。

int func();       /* */
/*           ^       */
/*           |       */
/* That whitespace is "after the function declaration". */

そのすべてが宣言です。宣言がされていないint func()と、その後に続きます;。宣言のint func();後に空白が続きます。

だから、問題は:宣言の後にセミコロンが必要ですか?もちろん違います。宣言にはすでにセミコロンが含まれており、セミコロンで終了しています。 宣言後のセミコロンは無意味です。対照的に、関数宣言の後のint func(); ;セミコロンになります

質問はほぼ間違いなく「trueまたはfalse:関数宣言の最後のトークンはセミコロンです」という質問をすることを意図していましたが、クイズの作成者が問題について明確に考えていなかったため、それは彼らが書いた質問ではありません。

私のアドバイスは、プログラミング言語のクイズを完全に回避することです。彼らはかなりひどいです。


面白い事実ですが、私たちがこの問題について話しています。C#では、これらはすべて合法です。

class C {}
class D {};
struct E {}
struct F {};

C#では、クラスまたは構造体の宣言は、自由裁量でセミコロンで終了する場合と終了しない場合があります。この奇妙な小さな機能は、C / C ++プログラマーがC#に来て、型宣言が無意味なセミコロンで終わるという指先で操作できるようにするために追加されました。設計チームは、この習慣があることで彼らを罰したくありませんでした。:-)


コメントは拡張ディスカッション用ではありません。この会話はチャットに移動さました
Samuel Liew

25

次のような関数も宣言できます。

int func(){
    return 1;
}

ステートメントは非常にあいまいです。正解は次のとおりです。関数の宣言方法によって異なります。

とにかく、私もfalseを選択しました。誰かに質問を報告できます。


3
とにかく、個人的なレベルで物事を置かないでください。重要なことは、関数の宣言と定義がどのように機能するかを理解したことです。そのため、あまり心配しないでください。質問が少なくともチェックされて続行されることを確認してください
Luca

11
もちろんです。正直に言えば、質問を間違えたことから、関数の宣言と定義について、私が正解したよりも多くのことを学びました。
ローガン

1
@Loganはあまり心配しないでください。あなたが必要なのは関数だけを書いて読む方法を知っているなら。私は個人的に、次のような種類の質問を嫌います。1。明確に定義されていない2.構文の理論的な知識をテストする。私にとってそれは筋肉の記憶のようなものです。私は各数字を書くとき、キーに楽に行くはずですが、数字を押す必要があるキーについてのテストを私に与えれば、キーボードがなければ物理的にアクションを実行することができません...
bolov

2
...共通の構文(関数など)を記述することは、2番目の性質になります。言語を切り替えただけで混乱する場合は、インテリセンスと構文の強調表示により、迅速で効率的なソリューションが実現します。時間とエネルギーをもっと役立つものに投資してください。
bolov

20

関数宣言の後にセミコロン( ';')は必要ありません。

正しいか間違っているか。

本当。宣言の後にセミコロンは必要ありません。どんな定義の後でも。いかなる発言の後も。

セクション7 [dcl.dcl]の構文で指定されているように、多くの種類の宣言はセミコロンで終了する必要があります。しかし、その後にもう1つ書く必要はありません。


1
Eric Lippertがすでにこの点について議論しているようです。すべての賛成投票で見落とされたと思います。自由に投票してください。
Marc van Leeuwen、

「Xは常に真である:真か偽か?」答えは「偽」になります。一体、どこにセミコロンを置く必要はありません。コンパイラは文句を言ってプログラムのコンパイルを拒否するかもしれませんが、それは世界の終わりではありません。私はそれを根本的な必要性とは呼びません。;)
Quuxplusone

@Quuxplusoneコンパイラがプログラムを拒否した場合、プログラムには関数宣言がありません:)
Ben Millwood

6

これは、関数を宣言するか定義するかによって異なります。関数を宣言する場合はセミコロン(;)を含める必要があり、関数を定義する場合はセミコロンは不要です。

宣言は次のようになります。

int add(int, int);

そして、定義はこのようなものです:

int add(int a, int b)
{
    // ...
}

10
この回答の問題は、定義と宣言が相互に排他的であることを示唆していることです。実際、すべての定義は宣言です。定義は宣言のサブセットです。
MSalters

6

他のほとんどすべての回答に同意しますが、質問は非常にあいまいであり、あなたの回答は技術的に正しいと述べ、別の見方をさせてください。

これは私がいつもそれらを呼んできた方法です:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

質問がこの用語を念頭に置いて構成されていると思います。

私の目には、定義と宣言はどちらも同じ概念です。「x = yを定義します」==「x = yを宣言します」。

しかし、もちろん、関数のプロトタイプ(上)と実際の関数の定義には大きな違いがあります。


私にとってあなたのプロトタイプは私が学んだ方法に基づいた宣言です(あなたが間違っていると言っているわけではありません)が、プロトタイプが引数の数と型、またはvoidを指定することも期待しますが、それは省略しました簡潔にするために。
David S

David S:はい、もちろん引数の数と型も含まれますが、簡潔にするために実際には省略しました(実際の関数宣言には引数がないことに注意してください)。しかし、完全な関数宣言がプロトタイプと呼ばれると私は本当に同意しません。Wikipediaの引用:「関数のプロトタイプまたは関数インターフェイスは、関数の名前と型のシグネチャ(アリティ、パラメーターのデータ型、戻り値の型)を指定する関数の宣言ですが、関数本体は省略しています。」
Opifex

@DavidS:C ++では、関数宣言は常にプロトタイプ(または定義)であり、void func();とまったく同じvoid func(void);です。これはCとは大きく異なります。Cvoid func();、コンパイラーに引数について何も通知せず、とは異なりvoid func(void);ます。後のプロトタイプまたは定義が良い考えです。それ以外の場合、呼び出し元はデフォルトの引数の昇格を適用する必要があります(例:float-> double、narrow整数型をint。可変引数への引数と同じルール。)
Peter Cordes

申し訳ありませんが、私はここでCに関連するものを見ていましたが、言語の変化に気づきませんでした。わかりやすくするためにコメントは削除しませんが、撤回したと見なします。
デビッドS

6

質問の答えが「直後」ではないのは残念です。たとえば、次のように書くことができます。

int func()  /* My function */ ;

または私は書くことができます:

int func()
int a = 42;

最初のケースでは、セミコロンは宣言の直後ではありませんが、それで問題ありません。

2番目のケースでは、宣言の「後」にセミコロンがありますが、直後にはありません。

エリック・リッパートは彼の答えで正しい考えを持っていると思います

「英語の文が終わってから、ピリオドが必要ですか?」間違いなく、文の終わりにはすでにピリオドがあり(そうでなければ文ではない)、したがって文のにピリオドがあってはなりません。


4
いいね。追加のピリオドでその文を終了します。あなたがそこで何をしたかわかる。
David S

2
int func() int a=42;コンパイルしません。別のコンマではなく、コンマが必要intです。この前日に投稿された@Arneの回答を参照してください。この回答で唯一新しいのは最後の段落で、英語の文章に例えられます。
Peter Cordes

1
2番目の例がコンパイルされたとは言いませんでした。宣言の「後に」セミコロンが必要であると言うのはあいまいであると私は指摘していました。私の例では、宣言の後にセミコロンがありましたが、コンパイルされません
Nick Gammon

1
これと同じ問題がエラーメッセージで発生します。C#のお気に入りの例は、「パラメーターパラメーターは、仮パラメーターリストの最後のパラメーターでなければなりません」です。ここで、代わりに「フロブはグロブリストの最後のグロブでなければならない」と言ったとします。これは、(1)すべての質問の最後に正確に1つのフロブがあるのと同様に、すべてのグロブリストの最後に正確に1つのフロブがあること、(2)グロブリストには任意の数のフロブを含めることができます、最後の項目はフロブでなければなりません。たとえば、偶数は任意の数の02468を持つことができますが、そのうちの1つは最後でなければなりません...
Eric Lippert

...(3)グロブリストには0個または1個のフロブがあります。コンテキストがわからない場合は、(1)が最もわかりやすい説明だと思いますが、「paramsパラメータ」の場合は(3)が正しい説明です。プログラミング言語要素の多くの非公式な説明には、私のテクニカルエディターの友人が「COIK」と呼ぶ特性があります-既知の場合にのみクリアしてください。資料を完全に理解していない場合、その説明は役に立ちませんが、完全に理解している場合は、説明は必要ありません。
Eric Lippert


4

ちょっとトリッキーな質問ですが、次のような意味の宣言という言葉を使用しました。

int example();

したがって、この場合は真実です。

彼らが実装という言葉を使っていたら、それは間違いでした。


2

セミコロン(;)は、このセミコロン(;)の後に新しいステートメントが始まることをコンパイラーに伝えるために使用されます。

したがって、セミコロン(;)は関数の宣言時にのみ必要だと思います。だから私によると、答えは本当でしょう。


ただし、宣言はステートメントではありません。
HolyBlackCat

しかし、関数宣言の後、コンパイラを使用して新しいコード行を実行しています。したがって、新しいコード行を実行する前に、コンパイラは前のコード行がどこで終了するかを知る必要があります。そうしないと、コンパイラはネイティブコード(つまり0101)を生成できます。
Jatinder

2

main()の前に関数が定義されている場合:

  • 関数はすでに定義されているため、セミコロンは必要ありません

main()の後に関数が定義されている場合:

  • セミコロンが必要なのは、その関数のプロトタイプを作成し、関数が終了することをコンパイラーに伝えるためです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.