2015-08-07 18 views
14

Se si utilizza extern C con file C++, ciò consente un comportamento C definito che non è definito in C++?Does extern C con C++ evita comportamenti non definiti che sono legali in C ma non in C++?

blah.h

extern "C" 
{ 
     struct x { 
      int blah; 
      char buf[]; 
     }; 

     char * get_buf(struct x * base); 
     struct x * make_struct(int blah, int size); 
} 

some_random.cpp

#include "blah.h" 

... 

x * data=make_struct(7, 12); 
std::strcpy(get_buf(data), "hello"); 

utilizza il comportamento definito nel membro di matrice flessibile di C, definita comportamento quando utilizzato in questo modo?

+0

Vedere di seguito, ma FAM di solito vengono compilati correttamente in C++. – Jason

+0

Nota: Poiché 'get_buf() make_struct()' usa solo un puntatore a 'struct x', perché' struct x' è definito anche in 'blah.h'? – chux

+0

Sto riportando questa domanda alla versione precedente. Se hai una nuova domanda, sei invitato a [chiedere] (http://stackoverflow.com/questions/ask), ma la tua ultima modifica sembra essere un tentativo di invalidare tutte le risposte che hai ricevuto. –

risposta

18

I membri di array flessibili sono una caratteristica standard di C, a partire dallo standard 1999. Non esistono in C++.

Il tuo codice non è valido C++. Il suo avvolgimento in extern "C" non lo modifica. Un compilatore C++ conforme deve almeno avvisare su di esso, e probabilmente dovrebbe rifiutarlo.

Accade che g ++ implementa membri di array flessibili in stile C come un'estensione di C++. Questo è perfettamente legittimo (i compilatori possono implementare estensioni), ma il suo uso non è portatile. Il suo comportamento, come quello di qualsiasi estensione di linguaggio, è definito dal compilatore, non dal linguaggio.

Se si compila con g++ -pedantic, si otterrà un avvertimento:

c.cpp:5:21: warning: ISO C++ forbids zero-size array ‘buf’ [-Wpedantic] 
      char buf[]; 
        ^

Se si desidera utilizzare i membri di matrice flessibili in stile C in un programma C++ senza fare affidamento su un interno specifico compilatore, è puoi compilare il tuo codice C come C e collegarlo al tuo programma C++. Non è possibile rendere il tipo con il membro flessibile dell'array visibile al codice C++, ma è possibile utilizzarlo internamente nel codice C e forse fornire l'accesso ad esso nel codice C++ tramite un puntatore opaco. Vedere the C++ FAQ per informazioni sulla combinazione di C e C++ all'interno dello stesso programma. (Oppure puoi semplicemente usare l'estensione g ++, a costo di non essere in grado di compilare il tuo codice con altri compilatori.)

(Suppongo che tu stia utilizzando g ++. Alcuni altri compilatori probabilmente implementano estensioni simili.)

+4

Potrebbe essere necessario nascondere la definizione effettiva di struct x dall'intestazione C++ e trattarla come un puntatore opaco tranne quando lo si accede tramite le funzioni C definite. –

+0

@KennyOstrom: Sì, questo è quello che stavo suggerendo (anche se non così chiaramente come hai fatto tu). Aggiornerò la mia risposta –

11

No.

extern "C" corrisponde alle caratteristiche di collegamento, in modo che i simboli chiusi possono essere collegati al dal C. Non passare il compilatore di "modalità C" per una sezione di codice.

+0

@GlennTeitelbaum Non importa: il problema è che i membri di array flessibili non * esistono * in C++. Anche se solo un compilatore C ha avuto modo di vederlo usato (non è il caso, si prova a 'std :: copy' ad esso), il compilatore C++ potrebbe strozzarsi solo sulla sua dichiarazione. – Quentin

+2

I membri di array reali e flessibili non esistono nel C++ standard, ma esistono nel dialetto g ++ di C++, come estensione specifica del compilatore. –

10

Una dichiarazione extern "C" riguarda solo il collegamento di funzioni esterne, in modo che il nome mangling non venga eseguito. Ciò non significa che le funzioni verranno compilate utilizzando le regole del linguaggio C anziché C++. In altre parole, incluso il codice in some_random.cpp non verrà definito il suo comportamento.

-5

È solo ASCII fino al momento in cui viene eseguito il compilatore. Quindi il preprocessore incollerà i file insieme, quindi il compilatore tratterà il risultato come qualsiasi lingua specificata.

Non è un membro di array C flessibile, è un file di testo. Il comportamento indefinito rimane.

+5

Manca il punto; la domanda è se "extern" C "' rende C/illegal C++ illegale in una sorta di C++ pseudo legale. –

+0

Non mi è venuto in mente che ci si potrebbe aspettare che extern C raggiunga così tanto, mentre determina quale linguaggio viene elaborato un file di testo come sembra gettare le persone. Grazie per il tuo commento. –

Problemi correlati