F6 Skapa C program
F6 Skapa C program
Ett C-program skapas i olika steg. Först sker preprocessor instruktioner. Dessa opererar enbart på källkodstexten och används t.ex. för att inkludera standard-bibliotekets API. Efter preprocessorn sker kompilering och assemblering. Då bildas en objekt modul med ändelsen ’.o’. Objektfilerna inndehåller maskinkod. I sista skedet länkas de olika objektmodulerna ihop till ett körbart program som på unix-system får ändelsen .out och på windows .exe
Preprocessorn
Preprocessorinstruktioner börjar med tecknet ’#’. Instruktionerna opererar enbart på texten. Med #define kan man definera konstanter och makron. T.ex.
#define PI 3.14 #define PRINTLN(x) printf(x"\n");
Man kan inkludera header-filer som innehåller funktionsdeklarationer (jämför med pythons import) för att få tillgång till färdiga definitioner. Preprocessorn klistrar in texten. För att skydda sig mot att inkluderade filer inkluderar samma fil många gånger används följande konstruktion ofta kallad include-guard.
#ifndef REDAN_INKLUDERAT_PROGRAM #define REDAN_INKLUDERAT_PROGRAM #include “local_fil.h” /* leta lokalt */ #include <system_fil.h> /* leta i systemet */ kod... #endif
Länkning
I objektfilerna behöver inte maskinkod som behövs finnas med. Det finns kvar anrop till okänd maskinkod. Signaturerna för dessa anrop stod i de inkluderade header-filerna. Vid länkningen letas definitionerna till dessa anrop och hittas de inte får man länkningsfel. Det kan vara jobbigt att felsöka länkningsfel, felmeddelandet kan vara kryptiskt och man har inget att debugga.
Manualer
För att ta reda på mer om de anrop man kan göra finns ett hjälpprogram som heter man. Hjälp om printf får man genom att skriva man printf i ett terminalfönster (eller använda google ‘printf format’). Hjälptexten förutsätter oftast att den som läser är väl förtrogen med C och unix.
Makefile
För att bygga de olika modulerna används ett make- program som tar som indata en fil som heter Makefile, make kan känna av vilka filer som behöver kompileras om genom att jämföra tidsstämplarna på objektfilen och källkodsfilerna. En makefile beskriver beroenden mellan olika mål (targets) och instruktioner som ska utföras.
FLAGS = -W -g all: nod.o program.o gcc $(FLAGS) -o utfil.exe nod.o program.o program.o: program.c gcc $(FLAGS) -c program.c nod.o: nod.c nod.h gcc $(FLAGS) -c nod.c # En regel för flera numrerade tester: make test03, make test01 etc test0%: @echo Tillverkar test # @ tar bort extra utskrift gcc –o test0$* test0$*.c # $* matchar % i regeln
Uppdelning i header-filer och implentationsfiler
När man programmerar C så brukar man lägga implementation i .c-filer. I header-filerna (.h) läggs funktionsdeklarationer och eventuellt egendefinierade datatyper. Det som ligger i header-filerna är gränssnittet utåt mot användaren.
Ett C-program i delar.
Genomgång av ett C-program. Kompileringsfel, länkningsfel m.m.
nod.h
struct post {
char name[29];
float bmi;
struct post * next;
};
typedef struct post Post;
void writePost(Post * p);
nod.c
#include "nod.h"
#include <stdio.h>
void writePost(Post * p) {
printf("Namn: %s\nbmi: %f\n", p->name, p->bmi);
}
program.c
#include <stdlib.h>
#include <stdio.h>
#include "nod.h"
int vikt; /* global variabel */
static float lengd; /* filglobal variabel */
int main(int argc, char * argv[]) {
Post * p = (Post *) malloc(sizeof(Post));
p -> next = (Post *) malloc(sizeof(Post));
printf("Vad heter du? ");
fscanf(stdin, "%s", p->name);
printf("Hur lång är du (m)? ");
fscanf(stdin, "%f", &lengd);
printf("Vad väger du (kg)? ");
fscanf(stdin, "%d", &vikt);
p -> bmi = vikt / (lengd * lengd);
writePost(p);
return 0;
}
test01.c
#include <stdio.h>
int main() {
printf("Detta är test 1\n");
}