2016-04-09 5 views
4

私は、Cで主な機能を最小限に表現する最も正直な方法についてたくさん考えていました。それは私にとって興味深い)。次のように長い間 mainをint main(...){}に定義する際に問題がありますか?

は、この日に、私はメインの定義好む:

int main(int argc, char **argv) 
{ 
    return 0; 
} 

これで私の問題は、それが引数を明示的になりますので、私は通常、にもかかわらず、これらの引数を使用したことがないということであるIそれらを書くためにコードについて十分気にしないでください。

だから私は、それが明示的に多くの人がint main(void){}定義の中でそうであるように関数は、引数を持たないことを言っていない、と私はそれに満足していので、これは、正直である

int main() 
{ 
    return 0; 
} 

を始めました。

しかし、私は、mainのバリデーシックな定義を使うと、関数が引数を持っているかのように私に "見える"ため、mainの定義がより快適になるという考えがありましたが、私は正しい今。

int main(...) 
{ 
    return 0; 
} 

このような表記の乱用に問題はありますか?つまり、...は、パターンの関数に使用されることを意図されています(次の引数の数が導き出されます)。一方、このメインはこのパターンに適合せず、技術的には表記の誤用です。

私は他の読者に誤解を招く表記があると理解しています(...多少の高度な概念であり、悪用されると誤解を招く)。コードを共有する際には他のプロトタイプも好む。私はそれが有効であるかどうかだけに興味があります。私が持っている

質問は以下のとおりです。

  1. がメインポータブルの可変引数定義であるか、それはいくつかのコンパイラはそれを好きでない可能性があります。

  2. このような定義を行うのは大丈夫ですか、そうすることでランタイム/コンパイル時に影響しますか?

+7

'(void)'および '(int、char **) '以外のシグネチャのサポートは実装定義のため、ベンダーに確認してください。コードは移植性がありません。 –

+1

'int main(...)'を試しましたか?あなたのコンパイラがそれを正当なものとして受け入れたら、どのコンパイラを使っていますか? – user3386109

+0

@ user3386109 "g ++(Debian 4.7.2-5)4.7.2"、 "Debian clangバージョン3.0-6.2(tags/RELEASE_30/final)(LLVM 3.0に基づいています)" – Dmitry

答えて

4

いいえ、それはです。絶対にが間違っています。

無効な構文なので間違っています。 n1548セクション6.7.6から:あなたは関数の引数に...を使用する場合

parameter-type-list: 
    parameter-list 
    parameter-list , ... 
parameter-list: 
    parameter-declaration 
    parameter-list , parameter-declaration 

Cの標準によると、あなたはそれの前に少なくとも一つの他の引数を持っている必要があります。文法からは、...は、カンマ,のパラメータリストの後にのみ表示され、のパラメータリストは空にすることはできません。

あなたのコンパイラはそれを受け入れるかもしれませんが、あまり意味はありません。コンパイラは無効なCをたくさん受け取り、とにかくそれをうれしくコンパイルします。

+1

私の嘘は、私の例は実際にはCとしてコンパイルされず、C++としてコンパイルされます。あなたが言ったように、これは無効なC構文であり、エラーが発生します。ISO Cでは '...'の前に名前付き引数が必要です。私が実験的な理由で行っていた拡張子.cppでコンパイルすると、これは起こりません。 – Dmitry

1

最初の2つのバージョンは正常です。あなたのニーズに合ったものを使用してください。

int main(...)でも有効であっても、この機能には適していません。

...は、関数が不特定の型の可変数の引数をとることを意味します。たとえば、printf()とします。これは、任意のタイプのゼロ以上の引数が続く形式の文字列を受け取り、その関数のシグネチャはこれを反映

int printf(const char* format, ...) 

main関数はそのようではありません。特定の型の引数の特定のリストを受け取ります。実行時に型を指定する必要があります。あなたの最初の例に示すように

は伝統的に、mainは2つの引数を取った:もちろん

int main(int argc, char **argv) 

をあなたはどちらかそれらを使用しないことにより、またはあなたの第二の例のように、メイン定義することで、これらの引数を無視することができます。int main()。それもOSX上で四番目の引数を取ることが

int main(int argc, char *argv[], char *env[]) 

:コンパイラ/ランタイムによって

mainは、環境変数を含む三番目の引数を取ることが

int main(int argc, char **argv, char **envp, char **apple) 

しかし、これらすべての中を特定の型の特定の引数があります。 mainprintfのようではありません。実際にはの変数の不確実な型の引数がありません。だからmain(...)は適切な署名ではありません。

+0

これは完全に真実ではありません。 Cの実装には、おそらく追加のenvパラメータがあります。しかし、最初の2つの引数(dword、pointer)は必要です。 – Dmitry

+1

さらに、関数に少なくとも1つの名前付きパラメータがない場合、可変引数を移植可能に使用することはできません。 –

+0

@KerrekSB私はこれを私の仕事で言いました。これが私が尋ねる理由です。それは表記法のまばらな乱用であり、説得力のあるものです。それが一貫して理解されている場合は、私たちは常にそれを行う、表記法を乱用することは大丈夫です。問題は、混乱している人以外はこの練習を行うことに本質的に不可能な/さらなる結果があるかどうかです(これは大丈夫ではないので、まだこの形で他の人には見せません)。 – Dmitry

関連する問題