Programmering i ANSI-C/Preprocessorn
Programmering i ANSI-C |
Preprocessorn
redigeraPreprocessorn är det första steget i kompileringen av ett C-program. Egentligen utgör preprocessorn ett separat program som översätter en källfil till en ny källfil där alla preprocessorinstruktioner har exekverats. Preprocessorinstruktioner är speciella instruktioner i C-källkoden som används för att styra kompileringen (villkorlig kompilering), definiera konstanter och makron samt inkludera huvudfiler. Varje preprocessorinstruktion står ensam på en rad och inleds med ett fyrkantstecken "#". Skrivs tecknet ensamt på en rad kallas det för ett tomt kommando:
#
Viktigt är att preprocessordirektivet står ensamt på en rad och att inget "vitt utrymme" (mellanslag eller tabuleringar) föregår hashtecknet (#) som alltså måste stå först på raden.
Övriga kommandon är:
#define - definierar konstanter och makron
redigeraPreprocessorinstruktionen "#define" kan definiera konstanter:
#define PI 3.14 float k = PI;
PI definierar här en konstant som kan användas senare i programmet. I själva verket kommer alla förekomster av ordet PI bytas ut av preprocessorn mot 3.14. Källfilen efter genomgång av preprocessorn kommer således att bli:
float k = 3.14;
Preprocessorinstruktionen har försvunnit och alla förekomster av PI har blivit ersatta.
Mera generellt kan define även användas för att definiera makron och då även ange parametrar, här är "x" parametern i makrot men kan vara vilka variabler som helst när det sedan används.
#define neg(x) (-x) y = neg( z ); /* Expanderar till */ y = (-z);
När makrot innehåller en operation som negationen ovan så bör man alltid skriva en parentes runt texten för att på så sätt undvika fel som kan uppstå i prioritetsordningen, (se prioritetsordningar för operatorer på tabellsidan).
Viktigt är att det inte får finnas något utrymme mellan makrotexten och parameterlistans parentes:
#define neg (x) (-x) y = neg( z ); /* Expanderar till */ y = (x) (-x)( z );
Det går även att skapa makron som gör jämförelser och sedan retunerar olika värden beroende på resultatet. Makrot "sgn" nedan retunerar -1 om ingångsparametern är mindre än noll annars 1:
#define sgn(x) (x < 0 ? -1 : 1) x = pow ( fabs ( x ), 2.0 ) * sgn ( x );
Om makrotexten är väldigt lång eller om man vill ange ett kodavsnitt som makro och låta texten löpa över flera rader så används omvänt snedstreck som radbrytningstecken.
/* Här hela "Hej världen" i ett makro: */ #define HEJVÄRLDEN #include <stdio.h>\ int main ( void )\ {\ printf ( "Hej världen\n" );\ return ( 0 );\ } /* Sedan själva "programmet" som bara är makrot ovan: */ HEJVÄRLDEN
Se även:
- Programexempel för orginaversionen av "Hej världen" med flera.
#include - inkluderar huvudfiler
redigeraPreprocessorinstruktionen "#include" inkluderar ytterligare källkod till den befintliga texten. Det görs vanligtvis i källkodens "huvud", (alltså den del av källkoden där definitioner och deklarationer görs och som föregår själva programkoden). Av den anledningen så kallas dessa tillägg av tradition för "huvudfil" och har normalt filtillägget *.h men det går även bra att inkludera andra C program (*.c) eller vilken annan textfil som helst under förutsättning att den inte innåller något annat än källkod för ANSI-C.
ANSI-C anger att det skall finnas ett antal standardliserade huvudfiler, (se: Tabeller -> standardbibliotek för en lista), dessa huvudfiler skall finnas tillgängliga i en mapp som heter "include".
/* Exempel på inkludering av ett standardbibliotek: */ #include <stdio.h>
Vinkelparenteser "< >" används endast till bibliotek som finns i den mapp som angets som kompilatorns include-mapp. Om huvudfilen sparats på något annat ställe (till exempel i den aktuella arbetsmappen) så skall dubbla citattecken " " användas i stället och hela sökvägen anges om så krävs för att operativsystemet som brukas av kompilatorn skall hitta rätt fil.
/* Exempel på inkludering av övriga filer: */ #include "C:/ANSI C/Mina huvudfiler/ANSI.h" #include "Funktioner.C"
Se även:
- Standardbibliotek för en utförlig beskrivning av dessa.
Tester för villkorlig kompilering
redigera#if #ifdef #ifndef #else #elif #endif
När flera preprocessordirektiv måste testas samtidigt, kan man använda sig av följande:
#if defined(villkor1) && !defined(villkor2) || defined(villkor3)
Övriga preprocessorkommandon
redigera#error #line #pragma #undef