logo

Een C-programma samenstellen: achter de schermen

De compilatie is het proces waarbij de broncode van de C-taal wordt omgezet in machinecode. Omdat C een taal op het middenniveau is, heeft het een compiler nodig om het in uitvoerbare code om te zetten, zodat het programma op onze machine kan worden uitgevoerd.

Het C-programma doorloopt tijdens het compileren de volgende fasen:



compilatieproces in c

Compilatieproces in C

Hoe compileren en draaien we een C-programma?

We hebben eerst een compiler en een code-editor nodig om een ​​C-programma te compileren en uit te voeren. Het onderstaande voorbeeld is van een Ubuntu-machine met GCC-compiler.

Stap 1: Een C-bronbestand maken

We maken eerst een C-programma met behulp van een editor en slaan het bestand op als bestandsnaam.c



t ff
  $ vi filename.c>

We kunnen een eenvoudig hello world-programma schrijven en opslaan.

Stap 2: Compileren met de GCC-compiler

We gebruiken de volgende opdracht in de terminal voor het compileren van ons bronbestand filename.c

  $ gcc filename.c –o filename>

We kunnen veel instructies doorgeven aan de GCC-compiler voor verschillende taken, zoals:



aaneengeschakelde strings
  • De optie -Wall schakelt alle waarschuwingsberichten van de compiler in. Deze optie wordt aanbevolen om betere code te genereren.
  • De optie -o wordt gebruikt om de naam van het uitvoerbestand op te geven. Als we deze optie niet gebruiken, wordt er een uitvoerbestand met de naam a.out gegenereerd.

Als er geen fouten in ons C-programma voorkomen, wordt het uitvoerbare bestand van het C-programma gegenereerd.

Stap 3: Het programma uitvoeren

Nadat het compilatie-uitvoerbare bestand is gegenereerd, voeren we het gegenereerde uitvoerbare bestand uit met behulp van de onderstaande opdracht.

  $ ./filename>

Het programma wordt uitgevoerd en de uitvoer wordt in de terminal weergegeven.

Wat gebeurt er tijdens het compilatieproces?

Een compiler converteert een C-programma naar een uitvoerbaar bestand. Er zijn vier fasen waarin een C-programma een uitvoerbaar bestand wordt:

    Voorbewerking van compilatie-assemblagekoppeling

Door het onderstaande commando uit te voeren, krijgen we alle tussenliggende bestanden in de huidige map, samen met het uitvoerbare bestand.

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

De volgende schermafbeelding toont alle gegenereerde tussenbestanden.

Tussenliggende bestanden

Laten we een voor een zien wat deze tussenbestanden bevatten.

1. Voorbewerking

Dit is de eerste fase waarin de broncode wordt doorgegeven. Deze fase omvat:

  • Verwijdering van opmerkingen
  • Uitbreiding van macro's
  • Uitbreiding van de meegeleverde bestanden.
  • Voorwaardelijke compilatie

De voorverwerkte uitvoer wordt opgeslagen in het bestandsnaam.i . Laten we eens kijken wat er in bestandsnaam.i zit: gebruik $vi bestandsnaam.i

In de bovenstaande uitvoer is het bronbestand gevuld met heel veel informatie, maar uiteindelijk blijft onze code behouden.

wat is obj in java
  • printf bevat nu a + b in plaats van add(a, b), omdat macro's zijn uitgebreid.
  • Reacties worden verwijderd.
  • #include ontbreekt, in plaats daarvan zien we veel code. Daarom zijn headerbestanden uitgebreid en opgenomen in ons bronbestand.

2. Compileren

De volgende stap is het compileren van bestandsnaam.i en het produceren van een; tussenliggend gecompileerd uitvoerbestand bestandsnaam.s . Dit bestand bevat instructies op assemblageniveau. Laten we dit bestand bekijken met behulp van $nano bestandsnaam.s terminale opdracht.

Assemblagecodebestand

Uit de momentopname blijkt dat het in assembleertaal is, die de assembler kan begrijpen.

3. Assembleren

In deze fase wordt de bestandsnaam.s als invoer genomen en omgezet in bestandsnaam.o door de monteur. Dit bestand bevat instructies op machineniveau. In deze fase wordt alleen bestaande code omgezet in machinetaal en worden de functieaanroepen zoals printf() niet opgelost. Laten we dit bestand bekijken met behulp van $vi bestandsnaam.o

json-bestand

Binaire code

4. Koppelen

Dit is de laatste fase waarin alle koppelingen van functieaanroepen met hun definities plaatsvinden. Linker weet waar al deze functies zijn geïmplementeerd. Linker doet ook wat extra werk, het voegt wat extra code toe aan ons programma die nodig is wanneer het programma start en eindigt. Er is bijvoorbeeld een code vereist voor het instellen van de omgeving, zoals het doorgeven van opdrachtregelargumenten. Deze taak kan eenvoudig worden geverifieerd met behulp van $size bestandsnaam.o En $grootte bestandsnaam . Via deze opdrachten weten we hoe het uitvoerbestand toeneemt van een objectbestand naar een uitvoerbaar bestand. Dit komt door de extra code die Linker aan ons programma toevoegt.

Opmerking: GCC doet standaard dynamisch koppelen, dus printf() is dynamisch gekoppeld in het bovenstaande programma. Raadpleeg dit, dit en dit voor meer details over statische en dynamische koppelingen.