Java jest często chwalona za niesamowitą przenośność, która, jak przypuszczam, wynika z JVM. Moje pytanie brzmi: co powstrzymuje C przed kompilacją / interpretacją / JIT'em? Jeśli tak, C można również napisać raz i sprawić, by działał na dowolnym urządzeniu. ale nie jest to popularny mechanizm przetwarzania programu w języku C.
Jakie są wady przetwarzania C w ten sposób, a także jakie zalety ma przetwarzanie Java w ten sposób i brak kompilacji do kodu maszynowego, poza oczywiście przenośnością?
Odpowiedzi:
C to, co nazwałbym językiem średniego poziomu. Jego celem jest służyć jako „asembler bardzo wysokiego poziomu”, dlatego tak dobrze działa jako cel kompilatora i dlaczego tak dobrze obsługuje przenośność.
Historycznie tłumaczy zwykle używano z językami wysokiego poziomu, w kontekście wywołań metod. W najprostszej formie interpreter po prostu analizuje każde słowo kluczowe w języku źródłowym wraz z powiązanymi z nim tokenami i przekształca je w wywołania metod i parametry. W praktyce większość tłumaczy ustnych przekształca język źródłowy w jakąś pośrednią reprezentację i to właśnie interpretacja jest interpretowana.
Co powstrzymuje C przed interpretacją lub odrzuceniem? Nic. Ale to nie jest racja bytu C.
źródło
Przede wszystkim warto zauważyć, że JVM firmy Sun został napisany w C. C jest bardzo popularnym językiem, gdy wymagana jest przenośność.
C język jest przenośny choć wiele C programy nie są. Wynika to z faktu, że C nie nakłada na programistę tylu ograniczeń ani nie przyjmuje tylu założeń. Jeśli programista C chce, aby jego programy były przenośne, musi nałożyć te ograniczenia na siebie.
W praktyce nie jest to o wiele trudniejsze niż życie z ograniczeniami, które narzuca na ciebie Java. Chodzi przede wszystkim o to, aby pamiętać o swoim endianizmie i prymitywnych rozmiarach oraz używać przenośnych bibliotek takich jak GTK + zamiast bibliotek specyficznych dla platformy.
Możesz stworzyć obiekt docelowy GTK + i kompilator C obsługujący maszynę wirtualną, nawet prawdopodobnie JVM, i uzyskać istniejący kod do pracy z niewielkimi zmianami. W rzeczywistości bez wyrzucania elementów bezużytecznych maszyna wirtualna C byłaby prawdopodobnie znacznie prostsza. Dlaczego jednak chcesz?
Odwrotna kompilacja Javy do kodu natywnego jest również wykonalna. Tak właśnie działa JIT. Dlaczego jednak chcesz? Jestem pewien, że istnieją projekty dla zwierząt domowych „tylko dlatego, że”, ale nie są one poważnie wykorzystywane.
źródło
Powiedziałeś:
I tam, w pierwszym zdaniu, mylisz się. Java nie jest przenośna z powodu JVM. Java jest przenośna, ponieważ język Java jest zdefiniowany w sposób, który nie pozostawia implementatorowi żadnej swobody w zachowaniu się programu.
Na przykład Java ma dwa typy „int” (32-bitowa liczba całkowita ze znakiem) i „long” (64-bitowa liczba całkowita ze znakiem). C i C ++ mają „int” (podpisane co najmniej 16 bitów), „long” (podpisane co najmniej 32 bity) i „long long” (podpisane co najmniej 64 bity). To dlatego, że C ma działać na wielu różnych procesorach i pozwala im zachowywać się inaczej.
C mógł zdefiniować stałe rozmiary dla tych typów. Gdyby tak było, wówczas 36-bitowe procesory nie mogłyby zaimplementować języka C. I tak naprawdę nie mogą implementować Java! Tak więc C pozwolił, aby język działał na różnych komputerach. Jest nieuniknione, że pozwala to na tworzenie kodu, który nie jest przenośny. To kwestia języka.
źródło
Java jest wysoce przenośna, ponieważ język jest przeznaczony na wirtualną maszynę Java, która, jak sama nazwa wskazuje, nie jest prawdziwą maszyną . Ponieważ można wdrożyć maszynę wirtualną na architekturze wielu różnych typów prawdziwych maszyn, program oparty na JVM jest wysoce przenośny.
Z drugiej strony C jest specjalnie zaprojektowany do działania na prawdziwym sprzęcie, ponieważ został stworzony w celu implementacji systemu operacyjnego, który wymaga pełnego dostępu do sprzętu. Oznacza to, że kod C nie jest szczególnie przenośny z założenia , a gdy przenosisz program C z jednej platformy na drugą, różne części, które są specyficzne dla architektury docelowej, będą musiały zostać przepisane do tego stopnia.
źródło
W rzeczywistości istnieją interpretowane wersje C , ale w większości są przeznaczone do szybkiego eksperymentowania, a nie do systemu produkcyjnego.
Nie są one powszechne, ponieważ w końcu, dlaczego miałbyś cierpieć wszystkie dziwactwa C, gdyby nie uzyskać małego, szybkiego i statycznego pliku wykonywalnego?
źródło
Teoretycznie zarówno C, jak i Java mogą być kompilowane do natywnego kodu, interpretowane lub kompilowane na maszynie wirtualnej.
Technicznym powodem, dla którego C nie jest skompilowany na maszynie wirtualnej, jest po prostu brak standardowej wirtualnej maszyny C.
I wydaje się, że nikt nie chce definiować wirtualnej maszyny C, ani nawet kompilować do wirtualnej maszyny Java (co jest całkowicie możliwe). Prawdopodobnie dlatego, że nikt, kto używa C, nie chce stracić swojej niezrównanej prędkości. Prawdopodobnie również dlatego, że C jest najsilniejszy w społeczności open source, która może z łatwością wykonywać przenośność poprzez kompilację (dystrybuować i rekompilować źródło i wykonywać), więc nie odczuwa takiej potrzeby przenośności wykonania (dystrybuowania i wykonywania pliku binarnego) jako zamkniętego deweloper źródła.
źródło
W rzeczywistości jest to zrobione. Istnieją główne kompilatory, które obsługują kompilację do LLVM (wiem, że clang to robi i myślę, że gcc również.). Ten LLVM może być JIT, podobnie jak kod Java jest kompilowany do kodu bajtowego, który jest JIT.
Jednak to, co sprawia, że Java jest „wieloplatformowa” w porównaniu z C, to że Java ma dużą bibliotekę wykonawczą, która została przeniesiona na wiele platform. C wyraźnie nie przestrzega tego paradygmatu.
źródło
Istnieją poważne różnice między Javą a C. Java jest izolowana od systemu operacyjnego za pośrednictwem wirtualnej maszyny Java (JVM). JVM oddziela system operacyjny od programu. Aplikacja Java może poprosić JVM o kawałek pamięci, a następnie JVM poprosi system operacyjny o tę pamięć. Istnieje wiele maszyn JVM dla różnych platform / systemów operacyjnych. JVM pozwala na uruchamianie tego samego programu Java na różnych platformach.
W przypadku C nie ma izolacji systemu operacyjnego. Programy C (zwykle) działają bezpośrednio na systemie operacyjnym, wykonując bezpośrednie wywołania systemu operacyjnego. To powoduje, że program C łączy się z określonym systemem operacyjnym / platformą. Każdy nietrywialny program będzie wykonywał połączenia z systemem operacyjnym. Ponadto programy C są kompilowane do kodu maszynowego, który jest specyficzny dla sprzętu. Skompilowanego programu C dla x86 nie można uruchomić bezpośrednio na procesorze ARM.
źródło