Przenośność w języku C.

10

Jak dokładnie określa się przenośność takiego języka jak C? Nauczyłem się, że kompilatory są specyficzne dla ISA. Jeśli to prawda, w jaki sposób C jest przenośny? A może tylko kod źródłowy napisany w C jest przenośny, ale nie pliki wykonywalne? Czy pliki wykonywalne ISA nie są specyficzne dla przykładów aplikacji dla x86 są oddzielne od aplikacji dla Apple (zakładając, że Apple używa mikroprocesora Motorola / PowerPC)?

KawaiKx
źródło

Odpowiedzi:

27

czy to tylko kod źródłowy napisany w C jest przenośny, a nie pliki wykonywalne?

Poprawny. Niektórzy nazywają to pisaniem raz, kompilują wszędzie.

http://en.wikipedia.org/wiki/Write_once,_compile_anywhere .

Inną alternatywą jest pisanie raz, uruchamianie wszędzie. Java jest tego dobrym przykładem.

http://en.wikipedia.org/wiki/Write_once,_run_anywhere

I chociaż można osiągnąć częściową przenośność między platformami, nigdy nie należy oczekiwać, że kod będzie działał wszędzie bez modyfikacji.

adolfojp
źródło
Kod źródłowy C nieprzenośny dla różnych kompilatorów, systemów ISA lub systemów operacyjnych bez sporo dodatkowych językowych shennaniganów. Proste rzeczy, takie jak rozmiar i wyrównanie standardowych typów, nie są standardowe w C, więc przenoszenie oprogramowania, które będzie wymieniało dane z innymi instancjami samego siebie, może być dość trudne. Zobacz GNU Autoconf / Automake, aby uzyskać (prawdopodobnie zaciemniony) przykład obręczy, przez którą programiści C będą przeskakiwać, aby uzyskać przenośność.
Tim Williscroft
3
@TimWilliscroft: Problemy z przenośnością są zazwyczaj spowodowane niestandardowymi bibliotekami i złymi praktykami programowania; i nie są spowodowane przez C lub jego standardowe biblioteki. Prostym przykładem może być użycie niestandardowego rozszerzenia GCC lub niepoprawna serializacja / deserializacja danych dla IO.
Brendan,
6

Nie dotyczy tylko ISA. Na przykład pytasz:

aplikacje dla x86 są oddzielne od aplikacji dla Apple?

Tak, mimo że Apple używa sprzętu x86. Pliki binarne C są specyficzne dla architektury i systemu operacyjnego.

vartec
źródło
1
@ Steven314: Twój komentarz jest styczny. Nie ma to nic wspólnego z tym, czy sprzęt jest standardowy, czy nie, a wszystko to z tym, że OS X ma inny format binarny (Mach-O) niż np. Linux (zazwyczaj ELF).
mipadi
@ Steve: EFI vs BIOS ma znaczenie tylko dla rozruchu i elementów wewnętrznych systemu operacyjnego; architektura sprzętowa, która jest zestawem instrukcji procesora, jest taka sama, ponieważ jest to ten sam procesor.
vartec
Komentarze zostały usunięte, głównie dlatego, że nigdy nie powinienem był uwzględniać Maca. Moja wzmianka o ABI (Application Binary Interface) i konwencjach wywołań może być nadal istotna (trzeci element do dodania do „architektury i systemu operacyjnego”). Nie mają one związku ze sprzętem, z tym wyjątkiem, że ABI mają tendencję do projektowania dla określonych architektur (np. Dostępnych rejestrów), ale są istotne dla przenośności binarnej. To nie jest problem z formatem pliku - ELF jest używany w systemach Windows i Linux (przez gcc), ale prawdopodobnie nie można przenosić pliku obiektowego z jednego do drugiego.
Steve314
@vartec powiedziałeś, że pliki binarne C są również specyficzne dla systemu operacyjnego, czy to dlatego, że sam O / S jest specyficzny dla ISA, a zatem binarne C stają się specyficzne dla O / S pośrednio?
KawaiKx,
@Saurabh - wszystkie natywne pliki wykonywalne są specyficzne dla systemu operacyjnego, ponieważ system operacyjny określa format pliku. Ponadto biblioteka standardowa C musi implementować wiele funkcji przez wywołanie systemu operacyjnego, więc nawet jeśli format pliku został ustandaryzowany, sam kod nie mógłby działać na innym systemie operacyjnym. Jest to standard w przypadku języków kompilowanych do kodu natywnego, w przeciwieństwie do niektórych kodów maszyn wirtualnych, takich jak JVM (Java Virtual Machine). Możliwe jest skompilowanie C dla maszyny wirtualnej, ale nigdy nie zrobiłem tego, o czym wiem. LLVM jest najbliżej, ale jest przeznaczony jako zaplecze kompilatora - nie jako środowisko kompilacji po uruchomieniu.
Steve314
5

czy to tylko kod źródłowy napisany w C jest przenośny, a nie pliki wykonywalne?

Dokładnie. Musisz ponownie skompilować swój program C na każdej platformie. Kompilatory C generują kod maszynowy, który jest przenośny tylko w bardzo ograniczonym zakresie, między komputerami o tym samym procesorze / architekturze pamięci i systemie operacyjnym. Dlatego widzisz różne dystrybucje binarne aplikacji wieloplatformowych (np. Przeglądarek), takich jak „Linux 64-bit Intel” lub „Mac OS X 32-bit PowerPC” (OK, ostatnia jest tylko ilustracją, wiem, że Apple przełączył się do Intela kilka lat temu :-).

Péter Török
źródło
3

Odpowiedzi na większość pytań, ale chciałbym dodać, że trwałość to kolejna rzecz, którą możesz wziąć pod uwagę.

Na przykład JAVA można napisać raz i uruchomić na dowolnej platformie, na której maszyna wirtualna (dziś nazywa się to „Runtime Environment”). Ale kolejną zaletą jest to, że możesz uruchomić kod Java 1.1 z 1995 roku na komputerze z 2011 roku. Nie jest to możliwe, jeśli kod został skompilowany na i386 i spróbujesz uruchomić go na architekturze AMD64.

Otrzymujesz również ulepszenia samej maszyny wirtualnej.

Następnie powiedziałbym, że ogólnie, przechodząc od najmniej przenośnych do bardziej przenośnych języków, jakie posiadasz: asembler, język kompilowany na niskim poziomie, taki jak C, następnie C ++, a następnie języki interpretowane lub te, które działają na maszynie wirtualnej.

Tak naprawdę nie jestem obrońcą Javy, przynajmniej nie dla języka ani społeczności, na przykład, ale jest to droga, jeśli szukasz przenośności i najmniejszej utraty wydajności w porównaniu do C.

TIK Tak
źródło
3

Dobre odpowiedzi na temat pisania po kompilacji w dowolnym miejscu.

Ludzie lubią myśleć o C jako przenośnym języku ze względu na jego popularność i duże prawdopodobieństwo, że kompilator C będzie dostępny dla przyszłych platform docelowych. Kolejnym czynnikiem jest standardowa biblioteka, która pomaga w wykonywaniu typowych zadań programistycznych w sposób niezależny od platformy.

Powiedziałbym więc, że przenośność języka zależy od:

  1. Poziom standaryzacji.
  2. Dostępność kompilatorów dla różnych platform / architektur.
  3. Głębokość i szerokość bibliotek przenośnych.

Realistycznie, choć prawie każda złożona aplikacja C wymaga przeniesienia na nową platformę z powodu zależności sprzętowych lub systemowych. Ten proces nazywa się przenoszeniem.

Guy Sirton
źródło
3

„Przenośność” ma wiele znaczeń. W odniesieniu do C oznacza to:

  • Kompilatory zostały zaimplementowane dla C dla szerokiej gamy platform sprzętowych i systemowych, co było wielką sprawą na początku lat 70-tych;

  • Istnieje uniwersalnie uzgodniony standard dla samego języka, w przeciwieństwie do każdej implementacji kompilatora, która rozpoznaje nieco inny wariant języka (ponownie, wielka sprawa, kiedy zaprojektowano C, ponieważ istniało wiele wariantów języków, takich jak Pascal i BASIC które nie były powszechnie uznawane);

  • Z powodu tego standardu zgodny kod spowoduje takie samo zachowanie, gdy zostanie skompilowany na różnych platformach.

Kod źródłowy jest przenośny, ale nowy binarny musi być generowane dla każdego celu.

Należy jednak pamiętać, że źródło C rzadko jest „trywialnie” przenośne; większość aplikacji wymaga wykroczenia poza to, co jest zdefiniowane w standardzie językowym, przy użyciu rozszerzeń unikatowych dla konkretnej platformy, więc w praktyce kod źródłowy nie jest w 100% przenośny.

Zauważ jednak, że C pozostawia wiele do implementacji. Dokładne rozmiary różnych typów danych, zachowanie przy przepełnieniu itp. Zależą od implementacji; standard określa minimalne wymagania, które musi spełniać implementacja, ale implementacja może przekroczyć te ograniczenia.

John Bode
źródło
0

Czymkolwiek jest ISA, C nie jest specyficzne dla ISA. Zakładam, że nie masz na myśli przestarzałego gniazda na karty rozszerzeń PC.

Istnieją kompilatory C zgodne ze standardami na bardzo wielu platformach i dopóki używasz w języku źródłowym funkcji w pełni zdefiniowanych przez standardy, powinieneś być w stanie skompilować je na dowolnym kompilatorze C dla dowolnej platformy.

Jednak jedną z nich jest to, że standard C pozostawia wiele zachowań funkcji, zarówno jako implementacja zdefiniowana, jak i zachowanie niezdefiniowane. Ma to na celu uczynienie języka C bardziej ogólnie przydatnym do programowania niskopoziomowego, unikając przypadków, w których niektóre dokładnie zdefiniowane zachowania nie pasują do tego, co sprzęt obsługuje na niektórych platformach. Jednak utrudnia to pisanie programów przenośnych.

Ponadto, w przeciwieństwie do niektórych języków, C nie jest dostarczany z ogromną biblioteką tego rodzaju, którą zapewniają Java lub C #. Możesz uzyskać bardzo przenośne biblioteki do robienia wszystkiego, ale musisz trochę popracować, aby je zbudować i zmusić do współpracy.

C ma oczywiście standardową bibliotekę, ale jej zakres jest stosunkowo ograniczony w porównaniu z Javą, C #, Pythonem itp.

Steve314
źródło
4
ISA = architektura zestawu instrukcji aka architektura sprzętowa
vartec