2010-04-13 20 views
30

Ho lavorato in C per così tanto tempo che il fatto che i compilatori aggiungano tipicamente un trattino all'inizio di uno extern è appena compreso ... Tuttavia, another SO question today mi ha fatto riflettere sul motivo reale per cui viene aggiunto il carattere di sottolineatura. A sostiene che una ragione è:Perché i compilatori C anteporre i caratteri di sottolineatura ai nomi esterni?

era pratica comune per i compilatori C anteporre un leader sottolineano a tutti gli identificatori di programma portata esterni per evitare scontri con i contributi di supporto per la lingua runtime

Penso che ci sia almeno un nocciolo di verità a questo, ma sembra anche che non risponda davvero alla domanda, poiché se il trattino di sottolineatura viene aggiunto a tutti gli esterni non sarà di grande aiuto nella prevenzione degli scontri.

Qualcuno ha una buona informazione sulla base logica del trattino basso principale?

è la parte di sottolineatura aggiunta del motivo per cui la chiamata di sistema Unix creat() non termina con una 'e'? Ho sentito che i primi linker su alcune piattaforme avevano un limite di 6 caratteri per i nomi. Se questo è il caso, quindi la preposizione di un carattere di sottolineatura a nomi esterni sembrerebbe essere un'idea pazzesca (ora ho solo 5 personaggi con cui giocare ...).

+2

Va notato che questo comportamento non viene praticato sui sistemi ELF moderni. Apparentemente era comune nelle piattaforme di Aout/Coff. –

+0

Perché Clang fa su OS X? come posso spegnerlo? – MarcusJ

risposta

17

era pratica comune per i compilatori C ad anteporre un leader sottolineano a tutti gli identificatori di programma portata esterni per evitare scontri con i contributi di supporto per la lingua runtime

Se il supporto runtime è fornito dal compilatore, è penserei che avrebbe più senso anteporre un underscore ai pochi identificatori esterni nel supporto di runtime!

Quando i compilatori C sono apparsi per la prima volta, l'alternativa di base alla programmazione in C su quelle piattaforme era la programmazione in linguaggio assembly ed era (e talvolta è ancora) utile per collegare insieme i file oggetto scritti in assembler e C. Quindi davvero (IMHO) il carattere di sottolineatura principale aggiunto agli identificatori C esterni era quello di evitare gli scontri con gli identificatori nello il proprio codice di assemblaggio.

(Vedi anche GCC's asm label extension, e di notare che questa sottolineatura anteporre può essere considerata una semplice forma di nome pressare lingue più complesse come il C++ usa più complicato nome mangling, ma questo è dove è iniziato..)

+0

Mi piace il sarcastico "GCC non ha ancora la capacità di memorizzare variabili statiche nei registri. Forse verrà aggiunto". commento nel documento collegato. –

+0

@MichaelBurr: probabilmente non è sarcastico. Su alcuni sistemi è possibile riservare un registro globale come puntatore a un'area di memoria (ad esempio 'R9' in alcune varianti di ARM EABI per il puntatore di base statico). –

3

Da quello che ho sempre sentito è di evitare conflitti di denominazione. Non per altre variabili esterne, ma anche per il fatto che quando si utilizza una libreria si spera che non sia in conflitto con i nomi delle variabili del codice utente.

1

Da Wikipedia:

era pratica comune per i compilatori C ad anteporre una sottolineatura di primo piano per tutti gli identificatori di programma portata esterni per evitare scontri con i contributi di supporto per la lingua di runtime. Inoltre, quando il compilatore C/C++ aveva bisogno di introdurre nomi nel collegamento esterno come parte del processo di traduzione, questi nomi venivano spesso contraddistinti da una combinazione di più caratteri di sottolineatura iniziali o finali.

Questa pratica è stata successivamente codificata come parte degli standard di linguaggio C e C++, in cui l'utilizzo dei trattini di sottolineatura principali era riservato per l'implementazione.
3

La funzione principale non è il vero punto di ingresso di un file eseguibile. Alcuni file collegati staticamente hanno il vero punto di ingresso che alla fine chiama main, e quei file collegati staticamente possiedono lo spazio dei nomi che non inizia con un carattere di sottolineatura. Sul mio sistema, in/usr/lib, ci sono gcrt1.o, crt1.o e dylib1.o, tra gli altri. Ognuno di questi ha una funzione "start" senza un carattere di sottolineatura che alla fine chiamerà il punto di ingresso "_main". Tutto il resto oltre a questi file ha un ambito esterno. La storia ha a che fare con la miscelazione di assemblatore e C in un progetto, in cui tutti i C erano considerati esterni.

5

se il compilatore c anteva sempre un carattere di sottolineatura prima di ogni simbolo, quindi il codice di avvio/c-runtime (che di solito viene scritto in assembly) può tranquillamente utilizzare etichette e simboli che non iniziano con un carattere di sottolineatura (come il simbolo ' inizio').

anche se si scrive una funzione start() nel codice c, viene generato come _start nell'output dell'oggetto/asm. (nota che in questo caso non esiste la possibilità che il codice c generi un simbolo che non inizia con un carattere di sottolineatura), quindi il codificatore di avvio non deve preoccuparsi di inventare simboli improbabili oscuri (come $ _dontuse42% $) per ciascuno di le sue variabili/etichette globali.

così il linker non si lamenterà di uno scontro di nomi e il programmatore è felice. :)

Quanto segue è diverso dalla pratica del compilatore che antepone un trattino basso nei suoi formati di output.

Questa pratica è stata successivamente codificata come parte degli standard di linguaggio C e C++, in cui l'utilizzo dei trattini di sottolineatura principali era riservato per l'implementazione.

che è una convenzione seguita, per le librerie di sistema e altri componenti di sistema. (e per cose come __FILE__ ecc.).

(notare che un tale simbolo (es: _Time) può provocare 2 sottolineature importanti (__time) nel output generato)

Problemi correlati