logo

Kompilering af et C-program: Bag kulisserne

Kompileringen er processen med at konvertere kildekoden til C-sproget til maskinkode. Da C er et sprog på mellemniveau, har det brug for en compiler til at konvertere det til en eksekverbar kode, så programmet kan køres på vores maskine.

C-programmet gennemgår følgende faser under kompileringen:



kompileringsproces i c

Kompileringsproces i C

Hvordan kompilerer og kører vi et C-program?

Vi har først brug for en compiler og en kodeeditor til at kompilere og køre et C-program. Nedenstående eksempel er en Ubuntu-maskine med GCC-kompiler.

Trin 1: Oprettelse af en C-kildefil

Vi opretter først et C-program ved hjælp af en editor og gemmer filen som filnavn.c



afkorte og slette forskel
  $ vi filename.c>

Vi kan skrive et simpelt Hello World-program og gemme det.

Trin 2: Kompilering ved hjælp af GCC-kompiler

Vi bruger følgende kommando i terminalen til at kompilere vores filnavn.c kildefil

  $ gcc filename.c –o filename>

Vi kan videregive mange instruktioner til GCC-kompileren til forskellige opgaver såsom:



  • Indstillingen -Wall aktiverer alle kompilatorens advarselsmeddelelser. Denne mulighed anbefales for at generere bedre kode.
  • Indstillingen -o bruges til at angive outputfilens navn. Hvis vi ikke bruger denne mulighed, så genereres en outputfil med navnet a.out.

Hvis der ikke er nogen fejl i vores C-program, vil C-programmets eksekverbare fil blive genereret.

heap-sorteringsalgoritme

Trin 3: Udførelse af programmet

Efter kompilering genereres eksekverbar, og vi kører den genererede eksekverbare ved hjælp af nedenstående kommando.

  $ ./filename>

Programmet vil blive udført, og outputtet vil blive vist i terminalen.

"hvad er forskellen mellem en løve og en tiger"

Hvad foregår der i kompileringsprocessen?

En compiler konverterer et C-program til en eksekverbar. Der er fire faser for et C-program til at blive en eksekverbar:

    Forbehandling Compilation Assembly Linking

Ved at udføre nedenstående kommando får vi alle mellemliggende filer i den aktuelle mappe sammen med den eksekverbare.

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

Følgende skærmbillede viser alle genererede mellemfiler.

Mellemliggende filer

Lad os en efter en se, hvad disse mellemfiler indeholder.

1. Forbehandling

Dette er den første fase, hvorigennem kildekoden sendes. Denne fase omfatter:

  • Fjernelse af kommentarer
  • Udvidelse af makroer
  • Udvidelse af de inkluderede filer.
  • Betinget kompilering

Det forbehandlede output gemmes i filnavn.i . Lad os se, hvad der er inde i filename.i: ved at bruge $vi filnavn.i

I ovenstående output er kildefilen fyldt med masser af info, men i sidste ende er vores kode bevaret.

  • printf indeholder nu a + b i stedet for add(a, b), det er fordi makroer er udvidet.
  • Kommentarer fjernes.
  • #include mangler i stedet ser vi masser af kode. Så header-filer er blevet udvidet og inkluderet i vores kildefil.

2. Kompilering

Det næste trin er at kompilere filnavn.i og producere en; mellemliggende kompileret outputfil filnavn.s . Denne fil er i instruktionerne på montageniveau. Lad os se gennem denne fil ved hjælp af $nano filnavn.s terminal kommando.

sharwanand

Samling kode fil

Snapshottet viser, at det er i assemblersprog, som assembleren kan forstå.

3. Samling

I denne fase tages filnavnet.s som input og omdannes til filnavn.o af montøren. Denne fil indeholder instruktioner på maskinniveau. I denne fase konverteres kun eksisterende kode til maskinsprog, og funktionskaldene som printf() løses ikke. Lad os se denne fil ved hjælp af $vi filnavn.o

java sammenligning

Binær kode

4. Sammenkædning

Dette er den sidste fase, hvor al sammenkædning af funktionskald med deres definitioner udføres. Linker ved, hvor alle disse funktioner er implementeret. Linker gør også noget ekstra arbejde, det tilføjer noget ekstra kode til vores program, som er påkrævet, når programmet starter og slutter. For eksempel er der en kode, der kræves for at opsætte miljøet, som at sende kommandolinjeargumenter. Denne opgave kan nemt verificeres ved at bruge $størrelse filnavn.o og $size filnavn . Gennem disse kommandoer ved vi, hvordan outputfilen stiger fra en objektfil til en eksekverbar fil. Dette er på grund af den ekstra kode, som Linker tilføjer til vores program.

Bemærk: GCC udfører som standard dynamiske links, så printf() er dynamisk linket i ovenstående program. Se dette, dette og dette for flere detaljer om statiske og dynamiske links.