1

Salut. J'ai un petit souci avec la programmation modulaire en C.

Voilà, je suis entrain de programmer un jeu eternity sur CVI. j'ai un fichier .c avec mon main, mes variables globales, et toutes les fonctions que j'ai créée. Mon fichier fait les 1700 lignes, et je voudrais séparer mes fonctions dans des .c et des .h.

Donc, j'ai mis toutes mes variables globales dans un fichier .h. J'y ai mis mes sturctures, et les prototypes de mes fonctions aussi. appelons ce fichier "variables.h"

Dans d'autres .c j'ai mis le corps de mes fonctions.

Dans les .c contenant mes fonctions, j'ai fait un include"variables.h". J'ai aussi mis un include"variables.h" dans mon main.c
Lors de la compilation, j'ai des variables qui sont déclaré plusieurs fois dans tout les fichiers...

Comment faut-il structurer les .h et les .c et qoui et où mettre les includes pour que le lien se fasse lors de la compilation?

Merci bien
Science is like sex: sometimes something useful comes out, but that is not the reason we are doing it. - Richard Feynman

2

Y-a-t-il les fameux :
#ifndef _TOTO_H_
#define _TOTO_H_

// Prototypes...

#endif

dans tes fichiers H?
avatar
la Nature nous montre seulement la queue du lion. Mais je suis certain que le lion a qui elle appartient pense qu'il ne peut pas se révéler en une fois en raison de son immense taille.

- Fondateur de Ti-Gen -: http://www.tigen.org

- Membre du Groupe Orage Studio -: http://oragestudio.free.fr/

- Mon site perso -: http://tisofts.free.fr

Projets TI68K en cours:
GFA-Basic = http://www.tigen.org/gfabasic
Arkanoid.
PolySnd 3.0.

3

Il faut mettre les variables dans un fichier .c et les déclarer extern dans le header.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

4

Dans mon .h j'ai les includes d'abord:

#include <userint.h>
#include <formatio.h>
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>
#include<time.h>
#include<stdlib.h>

et puis j'ai les isntructions suivantes. Donc ui, il ya bien un extern, et le ifndef...


#ifdef __cplusplus
extern "C" {
#endif

/*dans cette partie j'ai mis d'abord, mes structures, puis mes varuables globales, puis les prototypes des fonctions*/

#ifdef __cplusplus
}
#endif



DOnc je dois mettre les variables dans un .c, et que les prototypes et mes includes dans ce .h si j'ai bien compris? je vais essayer...
Science is like sex: sometimes something useful comes out, but that is not the reason we are doing it. - Richard Feynman

5

Alors, un .H contient normalement des déclarations formelles. Les déclarations effectives sont faites dans les .C.

C'est quoi la différence entre déclaration formelle et déclaration effective ? Je pense que tu es comme Mr Jourdain, tu as déjà utilisé ces concepts sans le savoir. Quand tu crées une fonction, tu fais deux choses : le prototype, et l'implémentation.

(...) }
Exemple : void fonction1(int blabla);    // <-- déclaration formelle

char variable;

int main()
{
  (...)
  fonction1();
  (...)
}

void fonction1(int blabla)    // <-- déclaration effective
{
La première ligne dit "il y a une fonction "fonction1" qui existe dans mon programme" mais c'est tout. Ensuite, plus bas, on donne le code de cette fonction, ce qu'elle doit exécuter, entre accolades.

Concrètement, dans le .H, il faut que tu rajoutes extern devant chaque déclaration de variable (pointeurs, scalaires, tableaux, structures, unions, enumérations, ...). Cela dit au compilateur "cette variable existe", sans réserver sa place en mémoire.

Cette réservation doit être faite dans le .C. En faisant une déclaration classique. Voici un programme organisé selon le modèle que je t'ai expliqué :


FICHIER .H :
extern void fonction1(int blabla);    // pour les fonctions t'es pas obligé de mettre "extern"

extern char variable;
FICHIER .C :
#include "fichier.h"

char variable;

int main()
{
  (...)
  fonction1();
  (...)
}

void fonction1(int blabla)
{
  (...)
}
avatar
Un site complet sur lequel vous trouverez des programmes et des jeux pour votre calculatrice TI 89 / Titanium / 92+ / Voyage 200 : www.ti-fr.com.
Quelques idées personnelles ici.

6

extern "C" n'est pas la même chose que extern, ça dit juste que les variables/fonctions portent le même nom interne qu'elles porteraient en C.

Il faut en plus déclarer chaque variable extern (pour les prototypes de fonctions, c'est implicit), c'est-à-dire:
extern int foo;
plutôt que:
int foo;
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

7

Ah je vois... merci beaucoup. Je crois que mon problème est en phase de résolution!
Science is like sex: sometimes something useful comes out, but that is not the reason we are doing it. - Richard Feynman

8

Bon, au passage, ce n'est pas une excellente idée d'utiliser beaucoup de variables globales.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

9

Bon alors pour programmer un peu proprement:
dans le .h tu mets les prototypes des fonctions publiques de ton "module". dans le .c celles qui sont privées

Si tu as besoin d'une variable pour un "module", déclare la en static dans le .c le symbole ne sera pas exporter (visibilité privée).
Si tu as besoin d'une structure, déclare la dans le .c et fait une forward déclaration dans le .h (tu auras une visibilité privée, et tu enlèves une dépendance de compilation)

10

que veut tu dire par une forward déclaration JackosKing? Merci.
Science is like sex: sometimes something useful comes out, but that is not the reason we are doing it. - Richard Feynman

11

fichier h:
#ifndef CircularBuffer_h
#define CircularBuffer_h

// forward declaration
struct SCircularBuffer;
typedef SCircularBuffer CircularBuffer;

CircularBuffer* CircularBuffer_create(t_size size);

#endif


fichier c:
#inclue "CircularBuffer.h"
struct SCircularBuffer{
 // whatever
};

CircularBuffer* CircularBuffer_create(t_size size){
 //whatever
}




12

r CircularBuffer;
Il me semble que struct SCircularBuffer; 
typedef SCircularBuffe
truct CircularBuffer;peut se remplacer partypedef s
avatar
Un site complet sur lequel vous trouverez des programmes et des jeux pour votre calculatrice TI 89 / Titanium / 92+ / Voyage 200 : www.ti-fr.com.
Quelques idées personnelles ici.

13

non pas dans ce cas là.

14

Ah ? pourquoi ?
avatar
Un site complet sur lequel vous trouverez des programmes et des jeux pour votre calculatrice TI 89 / Titanium / 92+ / Voyage 200 : www.ti-fr.com.
Quelques idées personnelles ici.

15

il me semble que cela ne fonctionne pas car tu définis juste le typedef et pas le référencement. Mais tu me mets un doute, va falloir essayer de le compiler pour voir. Je te laisse le faire wink

16

Il me semble que syntaxiquement c'est faux, déjà.
Il faudrait vérifier quoi...
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

17

Ce qui me paraît faux, c'est qu'on ne donne pas le contenu de la structure. typedef struct CircularBuffer {blabla}; ça marche, je ne déclare mes structures que comme ça (typedef et struct sur la même ligne).

JackosKing : j'essaierai wink
avatar
Un site complet sur lequel vous trouverez des programmes et des jeux pour votre calculatrice TI 89 / Titanium / 92+ / Voyage 200 : www.ti-fr.com.
Quelques idées personnelles ici.

18

tu peux faire ça: (une sorte de déclaration préalable)

struct _lienA;

struct _lienB {
   int a;
   struct _lienA *ptrLienA;
};

struct _lienA {
   int b;
   char trucmuche;
   struct _lienB *ptrLienB;
};

//et puis plus loin éventuellement...
typedef struct _lienA *lienA_t;
typedef struct _lienB *lienB_t;

on peut aussi écrire ça autrement, bref.
je l'ai jamais utilisé ailleurs

19

Thibaut (./5) :
déclarations formelles/effectives

Je n'avais jamais lu cette appellation (j'ai toujours lu déclaration/définition)

20

Euh, je vous signale que vous êtes en train d'écrire du C et que lui, il fait du C++ (cf. son extern "C").
En C++, le typedef est implicit, il suffit d'écrire struct CircularBuffer.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

21

Je sais pas je vois cela:
"Salut. J'ai un petit souci avec la programmation modulaire en C."