2009-03-28 9 views
6

Dla mojej klasy języków programowania, piszę pracę badawczą o niektórych pracach ważnych ludzi w historii projektowania języka. Jeden z CAR Hoare wydał mi się dziwny, ponieważ mówił przeciwko niezależnym technikom kompilacji używanym w C, a później w C++, zanim C stał się popularny.W jaki sposób języki takie jak C# i Java unikają C/C++ - jak niezależna kompilacja?

Ponieważ jest to przede wszystkim optymalizacja, aby przyspieszyć czasy kompilacji, co takiego jest w Javie i C#, które pozwalają uniknąć niezależnej kompilacji? Czy jest to technika kompilująca, czy też istnieją elementy języka, które to ułatwiają? Czy są jeszcze jakieś inne języki, które używały tych technik przed nimi?

Odpowiedz

5

Krótka odpowiedź: Java i C# nie unikają oddzielnej kompilacji; w pełni go wykorzystują.

Tam, gdzie są one różne, nie wymagają od programisty napisania osobnych plików nagłówkowych/implementacyjnych podczas pisania biblioteki wielokrotnego użytku. Użytkownik zapisuje definicję klasy raz, a kompilator wyodrębnia informacje równoważne "nagłówkowi" z tej pojedynczej definicji i umieszcza je w pliku wyjściowym jako "metadane typu". Tak więc plik wyjściowy (.jar pełen .class plików w Javie lub .dll w językach opartych na .NET) jest kombinacją plików binarnych i nagłówków w jednym pakiecie.

Następnie, gdy inna klasa jest kompilowana i zależy od pierwszej klasy, może spojrzeć na metadane, zamiast znajdować oddzielny plik dołączany.

Zdarza się, że są ukierunkowane na maszynę wirtualną, a nie na konkretną architekturę mikroprocesora, ale jest to osobny problem; mogą umieścić kod maszynowy x86 jako plik binarny i nadal mają podobne nagłówkowe metadane w tym samym pliku (w rzeczywistości jest to opcja w .NET, choć rzadko używana).

W kompilatorach C++ powszechne jest przyspieszenie kompilacji za pomocą "wstępnie skompilowanych nagłówków". Metadane w plikach .NET .dll i .class przypominają wstępnie skompilowany nagłówek - już przeanalizowany i zindeksowany, gotowy do szybkiego wyszukiwania.

Efektem jest to, że w tych nowoczesnych językach istnieje jeden sposób na modularyzację i ma on cechy doskonale zorganizowanego i zoptymalizowanego ręcznie systemu budowania modułowego C++ - całkiem fajnego, mówiącego: ASFAC++B.

4

IMO, jednym z najważniejszych czynników jest to, że zarówno java jak i .NET używają języków pośrednich; oznacza to, że skompilowana jednostka (jar/assembly) zawiera, jako warunek wstępny, wiele ekspresyjnych metadanych dotyczących typów, metod itp .; oznacza to, że jest on już dobrze przygotowany do sprawdzania referencji. Środowisko wykonawcze nadal i tak sprawdza, na wypadek gdybyś ciągnął szybko ;-p

Nie jest to bardzo odległe od MIDL, które wspiera COM, chociaż tam TLB jest często oddzielną jednostką.

Jeśli ja źle swój sens, proszę dać mi znać ...

+0

Ja * wierzę * zrozumiałeś mnie właściwie. Zasadniczo mam na myśli pomysł w C/C++, że każdy plik źródłowy jest własną jednostką kompilacji. Nie wydaje się, żeby tak było w C# lub Java. –

2

To wymaga obsługi języka (inaczej, kompilatory C/C++ i nie może to zbyt)

W szczególności wymaga, aby kompilator generuje autonomiczne moduły, które eksponują metadane, do których mogą odwoływać się inne moduły.

Zespoły .NET są prostym przykładem. Wszystkie pliki w projekcie są kompilowane razem, generując jedną bibliotekę dll. Ta biblioteka dll może być sprawdzana przez .NET, aby określić, które typy zawiera, tak aby inne zestawy mogły wywoływać zdefiniowane w niej funkcje.

I aby z tego skorzystać, musi być legalne w języku, aby odwoływać się do innych modułów.

W języku C++, co definiuje granicę modułu? Język określa, że ​​kompilator uwzględnia dane tylko w bieżącej jednostce kompilacji (plik .cpp + zawarte nagłówki). Nie ma mechanizmu określającego "Chciałbym nazwać funkcję Foo w pasku modułu, nawet jeśli nie mam prototypu ani nic podobnego podczas kompilacji". Jedynym mechanizmem do dzielenia się informacjami o typach między plikami jest #includes.

Istnieje propozycja dodania systemu modułów do C++, ale nie będzie to kodowanie w C++ 0x. Ostatnio widziałem, że plan polegał na rozważeniu TR1 po wyjściu 0x.

(Warto wspomnieć, że system #include w języku C/C++ był pierwotnie używany, ponieważ kompilacja przyspiesza kompilację. W latach 70-tych umożliwiła kompilatorowi przetworzenie kodu w prostym skanowaniu liniowym. nie musiałem budować drzew składniowych ani innych "zaawansowanych" funkcji. Dzisiaj tabele się zmieniły i stały się ogromnym wąskim gardłem, zarówno jeśli chodzi o użyteczność, jak i prędkość kompilacji.)

+0

Konstrukcja języków C była bardziej oparta na próbie zapewnienia, że ​​kompilacja byłaby możliwa na maszynach z ograniczoną pamięcią, niż przy próbie szybkiego jej wykonania. Obecnie istnieje stosunkowo niewiele systemów, których cały kod źródłowy nie mieściłby się łatwo w pamięci RAM typowego komputera stacjonarnego, ale C zaprojektowano w czasach, gdy duża maszyna miałaby mniej niż 1/16,000-ty więcej pamięci RAM niż dzisiejsze codzienne stacja robocza.Środowiska programistyczne musiały poczynić znaczne kompromisy między szybkością kompilacji a największą, praktyczną wielkością kompilacji. – supercat

2

Pliki obiektowe generowane przez C/C++ powinny być odczytywane tylko przez linker, a nie przez kompilator.

1

Podobnie jak w innych językach: IIRC Turbo Pascal miał "jednostki", których można użyć bez posiadania kodu źródłowego. Myślę, że chodzi o to, aby utworzyć metadane wraz ze skompilowanym kodem, który następnie może być użyty przez kompilator do określenia interfejsu do modułu (tj. Sygnatur funkcji, układu klas itp.)

Jeden problem z C/C++, który uniemożliwia jedynie zastąpienie #include jakimś plikiem #import, to także preprocesor, który może całkowicie zmienić znaczenie/składnię itd. Dołączonych/importowanych modułów. Byłoby to bardzo trudne (jeśli nie niemożliwe) z systemem modułowym podobnym do języka Java.

3

Można uznać plik Java .class za podobny do skompilowanego pliku nagłówkowego w języku C/C++. Zasadniczo plik .class jest pośrednią formą, której potrzebuje linker C/C++, a także wszystkimi informacjami zawartymi w nagłówku (Java po prostu nie ma oddzielnego nagłówka).

Postac komentarz w innym poście.

„Jestem w zasadzie znaczy nie idea w C/C++, że każdy plik źródłowy jest jego własna jednostka indywidualne kompilacja Ten robi tyle wydawać na przykład w C# lub Java. "

W języku Java (nie mogę mówić za C#, ale zakładam, że jest taki sam) każdy plik źródłowy jest jego indywidualną jednostką kompilacji. Nie jestem pewien, dlaczego uważasz, że tak nie jest ... może mamy różne definicje jednostki kompilacji?

Powiązane problemy