GeeksforGeeks (Polski)

C jest językiem średniego poziomu i potrzebuje kompilatora do przekształcenia go w kod wykonywalny, tak aby program mógł być uruchomiony na naszej maszynie.

Jak skompilować i uruchomić program w języku C?
Poniżej przedstawiamy kroki, które wykonujemy na komputerze Ubuntu z kompilatorem gcc.

kompilacja

  • Najpierw tworzymy program w języku C za pomocą edytora i zapisujemy plik jako filename.c
 $ vi filename.c
  • Schemat po prawej stronie przedstawia prosty program do dodawania dwóch liczb.

compil31

  • Potem skompiluj go używając poniższej komendy.
 $ gcc –Wall filename.c –o filename
  • Opcja -Wall włącza wszystkie komunikaty ostrzegawcze kompilatora. Opcja ta jest zalecana w celu wygenerowania lepszego kodu.
    Opcja -o służy do określenia nazwy pliku wyjściowego. Jeśli nie użyjemy tej opcji, to zostanie wygenerowany plik wyjściowy o nazwie a.out.

compil21

  • Po kompilacji zostanie wygenerowany plik wykonywalny, który uruchamiamy za pomocą poniższej komendy.
 $ ./filename 

Co dzieje się wewnątrz procesu kompilacji?
Kompilator przekształca program C w plik wykonywalny. Istnieją cztery fazy, w których program C staje się plikiem wykonywalnym:

  1. Preprocessing
  2. Kompilacja
  3. Assembly
  4. Linking

Wykonując poniższe polecenie, otrzymamy wszystkie pliki pośrednie w bieżącym katalogu wraz z plikiem wykonywalnym.

 $gcc –Wall –save-temps filename.c –o filename 

Następujący zrzut ekranu pokazuje wszystkie wygenerowane pliki pośrednie.

compil4

Po kolei zobaczmy, co zawierają te pliki pośrednie.

Pre-processing

Jest to pierwsza faza, przez którą przechodzi kod źródłowy. Faza ta obejmuje:

  • Usuwanie komentarzy
  • Rozszerzanie makr
  • Rozszerzanie dołączonych plików.
  • Kompilacja warunkowa

Przetworzone wstępnie dane wyjściowe są przechowywane w nazwie pliku.i. Zobaczmy, co jest wewnątrz filename.i: using $vi filename.i
W powyższym wyjściu plik źródłowy jest wypełniony mnóstwem informacji, ale na końcu nasz kod jest zachowany.
Analiza:

  • printf zawiera teraz a + b zamiast add(a, b) to dlatego, że makra zostały rozszerzone.
  • Komentarze są usunięte.
  • #include<stdio.h> brakuje zamiast tego widzimy dużo kodu. Więc pliki nagłówkowe zostały rozszerzone i dołączone do naszego pliku źródłowego.

Kompilacja

Kolejnym krokiem jest skompilowanie pliku filename.i i wyprodukowanie pośredniego skompilowanego pliku wyjściowego filename.s. Ten plik jest w instrukcjach poziomu asemblera. Przejrzyjmy ten plik używając $vi filename.s

image

Zrzut pokazuje, że jest on w języku asemblera, który asembler może zrozumieć.

Assembly
W tej fazie plik filename.s jest brany jako dane wejściowe i zamieniany przez asembler w plik filename.o. Plik ten zawiera instrukcje poziomu maszynowego. Plik ten zawiera instrukcje poziomu maszynowego. W tej fazie, tylko istniejący kod jest konwertowany na język maszynowy, wywołania funkcji jak printf() nie są rozwiązywane. Obejrzyjmy ten plik używając $vi filename.o

compil7

Linkowanie

Jest to ostatnia faza, w której wykonywane jest łączenie wywołań funkcji z ich definicjami. Linker wie, gdzie wszystkie te funkcje są zaimplementowane. Linker wykonuje również dodatkową pracę, dodaje do naszego programu dodatkowy kod, który jest wymagany podczas uruchamiania i kończenia programu. Na przykład, istnieje kod, który jest wymagany do ustawienia środowiska, jak na przykład przekazywanie argumentów linii poleceń. Zadanie to można łatwo sprawdzić za pomocą $size filename.o oraz $size filename. Dzięki tym komendom wiemy, że w jaki sposób plik wyjściowy zwiększa się z pliku obiektowego do pliku wykonywalnego. Dzieje się tak z powodu dodatkowego kodu, który linker dodaje do naszego programu.

compil8

compil8

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *