2009-03-28 13 views
6

Per la mia classe di linguaggi di programmazione, sto scrivendo un documento di ricerca su alcuni articoli di alcune persone importanti nella storia della progettazione linguistica. Uno di CAR Hoare mi ha colpito come strano perché parla contro tecniche di compilazione indipendenti usate in C e successivamente in C++ prima che C diventasse popolare.In che modo linguaggi come C# e Java evitano la compilazione indipendente simile a C/C++?

Poiché si tratta principalmente di un'ottimizzazione per accelerare i tempi di compilazione, che cos'è Java e C# che li rendono in grado di evitare l'utilizzo di compilazioni indipendenti? È una tecnica di compilazione o ci sono elementi del linguaggio che facilitano questo? E ci sono altri linguaggi compilati che hanno utilizzato queste tecniche prima di loro?

risposta

5

Risposta breve: Java e C# non evitano la compilazione separata; ne fanno pieno uso.

Dove differiscono è che non richiedono al programmatore di scrivere una coppia di file di intestazione/implementazione separati durante la scrittura di una libreria riutilizzabile. L'utente scrive la definizione di una classe una volta e il compilatore estrae le informazioni equivalenti alla "intestazione" da quella singola definizione e la include nel file di output come "tipo metadati". Quindi il file di output (uno .jar pieno di file .class in Java o un assembly .dll in lingue basate su .NET) è una combinazione di intestazioni binarie AND in un unico pacchetto.

Quindi quando un'altra classe viene compilata e dipende dalla prima classe, può guardare i metadati invece di dover trovare un file di inclusione separato.

Accade che si rivolgono a una macchina virtuale anziché a un'architettura di chip specifica, ma questo è un problema separato; potrebbero inserire il codice macchina x86 come binario e avere ancora i metadati di intestazione nello stesso file (questa è in effetti un'opzione in .NET, anche se raramente utilizzata).

Nei compilatori C++ è comune cercare di accelerare la compilazione utilizzando "intestazioni precompilate". I metadati nei file .NET .dll e .class sono molto simili a un'intestazione precompilata, già analizzati e indicizzati, pronti per una rapida ricerca.

Il risultato è che in questi linguaggi moderni esiste un modo di modularizzare e presenta le caratteristiche di un sistema di compilazione modulare C++ perfettamente organizzato e ottimizzato a mano, piuttosto elegante, che parla ASFAC++B.

4

IMO, uno dei maggiori fattori qui è che sia Java che .NET utilizzano lingue intermedie; ciò significa che l'unità compilata (jar/assembly) contiene, come prerequisito, molti metadati espressivi su tipi, metodi, ecc; il che significa che è già predisposto per il controllo di riferimento. Il runtime verifica comunque, nel caso in cui ne stiate tirando uno veloce ;-p

Questo non è molto distante dal MIDL che è alla base di COM, anche se il TLB è spesso un'entità separata.

Se ho frainteso la tua significato, per favore fatemelo sapere ...

+0

I * credi * mi hai capito bene. Fondamentalmente intendo l'idea in C/C++ che ogni file sorgente sia una propria unità di compilazione. Questo non sembra essere il caso in C# o Java. –

2

Si richiede un po 'di supporto per la lingua (in caso contrario, C/C++ compilatori lo farebbero troppo)

In particolare, si richiede che il compilatore genera moduli autonomi, che espongono i metadati che altri moduli possono fare riferimento per chiamarli.

Gli assembly .NET sono un esempio semplice. Tutti i file in un progetto sono compilati insieme, generando una dll. Questa DLL può essere interrogata da .NET per determinare quali tipi contiene, in modo che altri assembly possano chiamare funzioni definite in esso.

E per fare uso di questo, deve essere legale nella lingua per fare riferimento ad altri moduli.

In C++, cosa definisce il limite di un modulo? La lingua specifica che il compilatore considera solo i dati nella sua unità di compilazione corrente (file .cpp + intestazioni incluse). Non c'è alcun meccanismo per specificare "Mi piacerebbe chiamare la funzione Foo nella barra del modulo, anche se non ho il prototipo o qualcosa per esso in fase di compilazione". L'unico meccanismo che hai per condividere le informazioni sul tipo tra i file è con #include.

C'è una proposta per aggiungere un sistema di moduli a C++, ma non sarà in C++ 0x. L'ultima volta che ho visto, il piano era considerarlo per un TR1 dopo che 0x è uscito.

(Vale la pena ricordare che il sistema # include in C/C++ è stato originariamente utilizzato perché aveva accelerare compilazione. Negli anni '70, ha permesso al compilatore di elaborare il codice in una scansione semplice e lineare. E ' non è stato necessario creare alberi di sintassi o altre funzionalità "avanzate". Oggi le tabelle si sono trasformate ed è diventato un enorme collo di bottiglia, sia in termini di usabilità che di velocità di compilazione.)

+0

Il design dei linguaggi C si basava più sul tentativo di garantire che la compilazione fosse fattibile su macchine con memoria limitata, piuttosto che sul tentativo di renderlo veloce. Oggi, ci sono relativamente pochi sistemi il cui intero codice sorgente non si adatta facilmente alla RAM di una tipica macchina desktop, ma C è stato progettato in un'epoca in cui una macchina di grandi dimensioni avrebbe meno di 1/16.000 di RAM della quotidianità di oggi postazione di lavoro.Gli ambienti di sviluppo dovevano fare severi compromessi tra la velocità di costruzione e la dimensione di build più ampia e pratica. – supercat

2

I file oggetto generati da una C/C++ deve essere letto solo dal linker, non dal compilatore.

1

Come per altre lingue: IIRC Turbo Pascal disponeva di "unità" che è possibile utilizzare senza alcun codice sorgente. Penso che il punto sia creare metadati insieme a codice compilato che possa essere usato dal compilatore per capire l'interfaccia con il modulo (cioè firme di funzioni, layout di classe, ecc.)

Un problema con C/C++ che impedisce solo la sostituzione di #include con una sorta di #import è anche il preprocessore, che può modificare completamente il significato/sintassi ecc dei moduli inclusi/importati. Questo sarebbe molto difficile (se non impossibile) con un sistema modulare simile a Java.

3

Si potrebbe considerare un file java .class simile a un file di intestazione precompilato in C/C++. Essenzialmente il file .class è la forma intermedia di cui necessita un linker C/C++ e tutte le informazioni contenute nell'intestazione (Java non ha un'intestazione separata).

Formate il vostro commento in un altro post:.

"Io fondamentalmente significa non l'idea in C/C++ che ogni file sorgente è una propria unità di compilazione individuale Questa fa tanto sembrano per essere il caso in C# o Java. "

In Java (non posso parlare di C#, ma presumo che sia lo stesso) ogni file sorgente è una propria unità di compilazione. Non sono sicuro del perché penseresti che non lo sia ... forse abbiamo diverse definizioni di unità di compilazione?

Problemi correlati