2015-01-11 5 views
15

私は「C++」すべてがうまく行くようにコンパイルする場合は「C++」としてCの関数から{0}を返しますか?

struct A { 
    int x; 
    int y; 
}; 

struct A get() { 
    return {0};  
} 

をコンパイル対「C」としてコンパイルの間に次の食い違いを得ました。 しかし、 'C'としてコンパイルすると、私は取得しています:

エラー:予想される表現、私は実行して修正することができます

:違いはどこから来る

return (struct A){0};  

は、しかし、私は疑問に思います。この違いが生じている言語リファレンスを指し示すことはできますか?

+0

私は、C++コンパイラが自動的に戻り値を 'struct A'に変換すると仮定します。そして、c = +では 'struct A get()'だけを 'A get()'する必要はありません。 –

+1

'(*)'とは何ですか? – Ankur

+4

C++コンパイラ*以前*をC++ 11で試しましたか? [それは確かにそれもpukes](http://ideone.com/PBFlOR)。 – WhozCraig

答えて

24

2つのメカニズムは全く異なるメカニズムを使用していますが、そのうちの1つはC++ 11固有であり、もう1つはC99固有です。

最初のビット、

struct A get() { 
    return {0}; 
} 

は[stmt.return]に依存する(6.6.3(2))で

(...)Aを言うC++ 11、 braced-init-listを持つreturn文は、指定された初期化子リストからcopy-list-initializationによって関数から返されるオブジェクトまたは参照を初期化します。 [例:

std::pair<std::string,int> f(const char *p, int x) { 
    return {p,x}; 
} 

から端例]

この通路は、(C++ 11の前にもC++)Cには存在しないので、Cコンパイラは、それを扱うことができません。一方

struct A get() { 
    return (struct A){0}; 
} 

は、いくつかのC++コンパイラ、特にGCCは、言語拡張としてそれを提供するが(C++に存在しない「化合物リテラル」と呼ばれるC99機能を使用して、GCCは約警告それは - ペディンと一緒に)。このセマンティクスは、C99標準のセクション6.5.2.5で詳細に説明されています。お金の引用は、初期化子の中括弧で囲まれたリストに続いて括弧で囲んタイプ名で構成されてい

4後置式はリテラル化合物です。それは初期化子リストによって値が与えられる無名のオブジェクトを提供します。 (脚注80)

80)これはキャスト式とは異なります。たとえば、キャストはスカラー型またはvoidへの変換のみを指定し、キャスト式の結果は左辺値ではありません。

この場合、(struct A){0}は戻り値にコピーされ返される無名のオブジェクトです。 (現代のコンパイラはこのコピーを削除するので、ランタイムオーバーヘッドを恐れる必要はありません)。

そしてそこには、章と節があります。なぜこれらの機能がそれぞれの言語で行われているかが魅力的な議論になるかもしれませんが、それぞれの標準化委員会の外にいる誰もが質問に対する正式な回答をすることは難しいです。どちらの機能もCとC++の分割方法の後に導入されており、それらは並んで開発されていません(そうするのは意味がありません)。小さな事でも発散は避けられません。

+0

うまく形成された説明。ありがとう – sramij

+0

ところで、実際に '(構造体A){0}'が返っていますか? AFAIK、 'return'文は'(struct A){0、0} 'でなければなりません。 – haccks

+1

@hackks:括弧で囲まれた初期化子リストに記載されていないものはゼロ初期化されています(C99の6.7.8(21)を参照)。これは通常の構造体と配列の初期化でも発生します。 – Wintermute

関連する問題