2015-01-11 28 views
15

ho ottenuto le seguenti discrepanza tra la compilazione come 'C' contro la compilazione come 'C++'restituisce {0} da una funzione in C?

struct A { 
    int x; 
    int y; 
}; 

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

Quando si compila come 'C++' tutto va bene. Tuttavia, durante la compilazione come 'C'; sto ottenendo:

errore: attesa espressione

che posso risolvere facendo:

return (struct A){0};  

Tuttavia, mi chiedo dove la differenza proviene. Qualunque punto nel riferimento alla lingua da cui proviene questa differenza?

+0

Suppongo che il compilatore C++ converta automaticamente il valore restituito in 'struct A'. E in c = + non hai bisogno di 'struct A get()' just 'A get()' –

+1

cos'è '(*)'? – Ankur

+4

Lo hai provato con un compilatore C++ * precedente * a C++ 11? [Abbastanza sicuro che ci possa essere anche lì] (http://ideone.com/PBFlOR). – WhozCraig

risposta

24

I due utilizzano meccanismi completamente diversi, uno dei quali è specifico per C++ 11, l'altro è specifico per C99.

Il primo bit,

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

dipende [stmt.return] (6.6.3 (2)) in C++ 11, che dice

(...) A dichiarazione di ritorno con una lista di avvio inizializza l'oggetto o il riferimento da restituire dalla funzione mediante l'inizializzazione dell'elenco di copia dall'elenco di inizializzazione specificato. [Esempio:

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

- fine esempio]

Questo passaggio non esiste in C (né C++ prima C++ 11), quindi il compilatore C non può gestire.

D'altra parte,

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

usa una caratteristica C99 chiamata "letterali composti" che non esiste in C++ (anche se alcuni compilatori C++, in particolare gcc, forniscono come un'estensione del linguaggio; gcc segnalazioni relative con -pedantic). La semantica è descritta in dettaglio nella sezione 6.5.2.5 della norma C99; la citazione denaro è

4 Un'espressione postfissa che consiste di un nome di tipo tra parentesi seguita da una lista brace-chiuso di initializers è un letterale composto. Fornisce un oggetto senza nome il cui valore è dato dall'elenco di inizializzazione. (nota 80)

80) Si noti che questo differisce da un'espressione cast. Ad esempio, un cast specifica una conversione in tipi scalari o solo void e il risultato di un'espressione cast non è un lvalue.

Quindi in questo caso (struct A){0} è un oggetto senza nome che viene copiato nel valore restituito e restituito. (nota che i compilatori moderni elideranno questa copia, quindi non devi temere il sovraccarico di runtime da esso)

E lì ce l'hai, capitoli e versetti.Perché queste caratteristiche esistano come nelle loro rispettive lingue può rivelarsi una discussione affascinante, ma temo che sia difficile per chiunque al di fuori dei rispettivi comitati di standardizzazione dare una risposta autorevole alla domanda. Entrambe le funzionalità sono state introdotte dopo la suddivisione di C e C++, e non sono sviluppate fianco a fianco (né avrebbe senso farlo). La divergenza è inevitabile anche nelle piccole cose.

+0

spiegazione ben formata. grazie – sramij

+0

BTW, Che cosa effettivamente '(struct A) {0}' sta tornando? AFAIK, l'istruzione 'return' dovrebbe essere' (struct A) {0, 0} '. – haccks

+1

@hackks: le cose che non sono menzionate in un elenco di inizializzazione rinforzato sono inizializzate a zero (vedere 6.7.8 (21) in C99). Questo succede anche nelle normali inizializzazioni di strutture e array. – Wintermute

Problemi correlati