🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: nl.comp.programmeren
Article #734

Re: Opbouw grote programma's via opsplitsing source-files

#734
From: Yvon Rozijn
Date: Sun, 07 Nov 1999 00:00
127 lines
5893 bytes
On Sat, 06 Nov 1999 22:29:48 +0100, Bart Vandewoestyne
<Bart.Vandewoestyne@skynet.be> wrote:

>Aangezien ik van plan ben om een grote applicatie te schrijven gebruik
>makend van de GTK bibliotheek in Linux wil ik me toch eerst informeren
>hoe je een groot programma best aanpakt.
>Doe ik het bijvoorbeeld best op volgende manier (voorbeeldsituatie):
>
>In de main.c komt:
>
>#include "sub.h"
>
>int main(void)
>{
> printf("Hoofdfile\n");
> zetboodschap();
>}
>

Korrekt, alleen zal er nog een #include <stdio.h> bij moeten.

>Dan maak ik een header file sub.h aan met volgende inhoud:
>
>#include "sub.c"

Nee. Het voordeel van je programma opsplitsen in verschillende
sources, is dat je niet elke keer alles hoeft te compileren, maar
alleen die sourcefile waarin wat veranderd is. Als je sub.c (via
sub.h) in main.c opneemt, compileer je wel elke keer alles opnieuw,
ook al is bijvoorbeeld alleen sub.c veranderd en main.c niet.

Een goede manier op je programma op te splitsen is: verschillende .c
files met funkties (bodies) die funktioneel bij elkaar horen zet je
bij elkaar in een .c file. In deze file kun je ook bv globale
variabelen definieren, die alleen in deze funkties worden gebruikt
("private").
Bij elke .c file hoort dan een .h header file waarin de prototypes
staan van alle funkties in die source die je vanuit andere gedeelten
van je programma wilt benaderen. Funkties die *alleen* binnen die ene
.c source worden gebruikt waarin ze ook (met body) zijn gedefinieerd,
neem je hier niet op. In de .h file kun je ook de struct (en in C++ de
class) definities opnemen die je nodig hebt om de publieke funkties in
deze .c file aan te roepen. Tenslotte neem je hier de declaraties
(niet de definities) op van eventuele publieke globale variabelen. De
definitie van die variabele zit dan in de .c file. (Voorbeeld van
declaratie: extern int myvar; definitie: int myvar=33;)
In iedere .c file waarin een van de funkties uit bv sub.c wordt
gebruikt, neem je een #include "sub.h" op. Een goede compiler
waarschuwt als je dat niet gedaan hebt, omdat de prototype van de
aangeroepen funktie in dat geval ontbreekt.

Eventueel kun je vanuit een .h file andere .h files #include'n, maar
alleen als je als het ware voortbouwt op struct-definities uit die
tweede .h file. Om te voorkomen dat een .h file twee keer wordt
ge-included, neem je aan het begin op:
#ifndef NAAMVANDEFILE_H
#define NAAMVANDEFILE_H
en aan het einde:
#endif

Je sub.h file wordt dus:

#ifndef SUB_H
#define SUB_H

void zetboodschap(void);

#endif

>en in mijn sub.c komt dan te staan:

#include "sub.h"
// altijd de eigen .h file includen, hier staan nl de prototypes en de
// struct definities die je in deze source nodig hebt.

#include <stdio.h>

void zetboodschap(void)
{
 printf("Subfile\n");
}

>Nu is mijn vraag ook: stel dat ik bijvoorbeeld gebruik maak van
><stdio.h> en dat ik die header file nodig heb in verschillende .c
>files.  Moet ik deze dan in elk van die .c files includen ?  Of waar
>include ik ze dan best?

Het best in elke .c file waarin je ze nodig hebt.

>Indien mijn programma uit meerdere files bestaat, kan ik dan toch
>compileren met ��n enkele regel in te typen?

Daar zijn makefiles voor uitgevonden.

>  Kan iemand me dan kort
>uitleggen waarom 'MakeFiles' bestaan?  Kan ik inderdaad met die ene
>regel compileren of maak ik best zo'n MakeFile aan?

Een makefile bevat kort gezegd een lijst van modules waaruit je
programma bestaat, met voor elke module de (source en header)files
waar die module afhankelijk van is. Bij main.o staat dat deze
afhankelijk is van main.c en van sub.h. Dus als sub.h verandert, moet
main.c opnieuw gecompileerd worden (tot main.o). Maar als alleen sub.c
verandert en sub.h hetzelfde blijft, hoeft dat niet.
De makefile zal ook de executable noemen, met alle .o files waar die
executable van afhankelijk is.
Tenslotte bevat de makefile bij iedere file, op welke manier deze file
wordt geconstrueerd. Bij .o files staat dus dat de bijbehorende .c
file moet worden gecompileerd, bij het executable staat dat de .o
files (plus de startup module) tot een geheel moeten worden gelinkt.

Bij grote projekten met veel sources en header files is het niet te
doen om de makefile handmatig bij te houden (als je een .h file
vergeet te noemen, wordt een module niet opnieuw gecompileerd en kun
je hele vreemde en nauwelijks te vinden fouten krijgen). Daarom zijn
er verschillende utilities voor.
Maar als je eenmaal zo'n makefile hebt, kun je met het commando make
in een keer alles compileren. De make utility kijkt dan wat er nodig
is om het executable te maken, en of alles nog up-to-date is. Dat wil
zeggen: of elke file van latere datum is dan alle files waar die file
van afhankelijk is. Wat niet meer up-to-date is wordt opnieuw
gecompileerd, en alleen dat: wat nog wel goed is hoeft niet opnieuw
gecompileerd te worden. Zo wordt er geen werk teveel gedaan.

--
E-mail: y r o z i j n @ x s 4 a l l . n l
Web:    http://www.xs4all.nl/~yrozijn/
Technical Details
Message-ID: <38256451.5769509@news.xs4all.nl>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <38249DCC.ABDE8533@skynet.be>

Show Full Headers
Complete Article Headers
X-Google-Language: DUTCH,ASCII
X-Google-Thread: 107324,bea50703bd2c4537
X-Google-Attributes: gid107324,public
X-Google-Thread: 100a19,bea50703bd2c4537
X-Google-Attributes: gid100a19,public
X-Google-Thread: fcea4,bea50703bd2c4537
X-Google-Attributes: gidfcea4,public
From: yrozijn@nozpam.xs4all.nl (Yvon Rozijn)
Subject: Re: Opbouw grote programma's via opsplitsing source-files
Date: 1999/11/07
Message-ID: <38256451.5769509@news.xs4all.nl>
X-Deja-AN: 545501973
References: <38249DCC.ABDE8533@skynet.be>
X-Complaints-To: abuse@xs4all.nl
X-Trace: news1.xs4all.nl 941975154 5805 194.109.137.140 (7 Nov 1999 11:45:54 GMT)
Organization: XS4ALL Internet BV
NNTP-Posting-Date: 7 Nov 1999 11:45:54 GMT
Newsgroups: nl.comp.programmeren,be.comp.programming,be.comp.os.linux