IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

variables globales extern & implicite target Makefile ;


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut variables globales extern & implicite target Makefile ;
    Salut les C,

    J'ai un programme de plusieurs fichiers sources ayant chacun sont header et j'utilise un Makefile pour compiler chaque fichier *.c.

    D'abords le sujet N° 1: les variables externes marqué extern.

    J'ai une structure de type GUI ressemblant a ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    /** File gui_structure.h . **/
     
    typedef struct {
     
      GtkWidget *icon ;
     
      GtkWidget *label ;
     
      GtkWidget *accel_label ;
     
    } MenuItem ;
     
    /** etc more typedef struct { ... } **/
     
    typedef struct {
     
      MenuItem files ;
     
      MenuItem action ;
     
      GtkWidget *hbox ;
     
      // etc...
    } GUI ;
     
    // Etc...
    Puis j'ai un fichier de déclaration de variables globale:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /** Files global_variables.h **/ 
     
    GUI *gui ;
    Puis je me retrouve souvent a n'avoir besoin que de gui->notebook_editor ou gui->notebook_terminals, dans mes fichiers.

    Alors dans mes fonctions je déclare:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void callback(GtkWidget *widget, gpointer user_data) {
     
      extern GUI *gui ;
     
      // ...
     
      return ;
    }
    Alors j'ai un doute: est que ça serai mieux de déclarer un alias de gui->notebook_editor sous forme de pointeur déclarer comme une variable globale ?

    Je ne le fait pas pour l'instant car je pense que si je déclare:
    cela revient au même: copier l'adresse du pointeur de toute la structure GUI *gui c.a.d la taille d'un pointeur.

    A la place d'utiliser un pointeur alias sur un seule GtkWidget *.

    NOTE: je ne peut pas passer la variable gui par l'argument user_data.



    Sinon j'ai un problème avec le Makefile.

    Quand j'ajoute un fichier je l'ajoute a une liste (a savoir que l'arborescence est complexe).

    Et j'aimerai utiliser le feature de règle implicite...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    SRC_FILES = ./folder1/file1.c \
                       ./folder2/file2.c \
                       ./folder3/subfolder1/file3.c 
     
    TMP = $(notdir $(SRC_FILES:.c=.o))
     
    OBJECTS = $(TMP:%=./build/%) 
     
    prgname: $(OBJECTS)
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
     
    $(word 1, $(OBJECTS)): $(word 1, $(SRC_FILES))
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
     
    # Etc ...
     
    # My try for implicite rules build:
     
    VPATH = ./folder1 ./folder2 ./folder3/subfolder1 ./build
     
    %o: %c $(SRC_FILES) $(OBJECTS)
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
     
     
    # What lack me to success implicte build ?
    Vous avez remarquer que j'utilise un dossier pour le build ce qui rend la chose plus difficile.

    Merci pour vos réponses éclairées et votre précieuse aide.

  2. #2
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Mes 2 centimes :

    1. Je n'ai pas bien saisi l'interrogation au sujet des alias de fonction, par contre si tu déclares GUI *gui; dans ton .h tu obtiendras une variable gui par module de compilation. De plus tu n'as pas besoin de le déclarer en extern dans tes fonctions puisque la variable est déjà visible (si tu inclus le header). Ce que je ferais à ta place :
    Code gui_public.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    extern GUI *gui;
     
    /* initialize UI */
    int gui_init(GUI *);
    Code gui.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    GUI *gui;
     
    int gui_init(GUI *gui) {
        // ...
    }
    Code main.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdlib.h>
    #include <stdio.h>
     
    #include "gui_public.h"
     
    int main(int argc, char *argv[]) {
        if ((int r = gui_init(gui))) {
            fprintf(stderr, "gui initialization failed with code %d", r);
            exit(EXIT_FAILURE);
        }
     
        gui->do_stuff();
     
        // ...
     
        return 0;
    }


    2. N'écris pas tes makefile à la main lorsque ton projet commence à prendre de l'envergure, on n'est plus en 1988. Utilises plutôt autotools (si tu ne connais pas je te recommande le très bon guide d'Alexandre Duret-Lutz) ou autre chose (waf, CMake...).

  3. #3
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    D'accord nous ne somme plus en 1988,

    mais je pense qu'il faut connaître la syntaxe des Makefile avant d'utiliser les autotools.

    Je dit ça empiriquement (par expérience) car j'ai appris les autotools sans connaître le fond de l'outil make, sur lequel sont basé grand nombre de projets.

    Et ça ne m'a pas vraiment réussis car avant de lire le GNU manual de make, je comprenait mal les autotools.

    Et ça tombe bien que tu me dise cela car c'est pour générer un Makefile que je pose la question dessus.

    Je pense qu'il faut apprendre a lire et a écrire avant de générer des données, car l'ont dit que l'ordi est une extension de son cerveau... a méditer.

    Sinon je n'ai aucun problème avec mon programme et mes variables globales mais je voulait simplement savoir si il est plus court d'écrire un pointeur de GtkWidget au lieu d'un pointeur sur une structure de GtkWidget déclaré comme extern ?

    Mais sûrement que un pointeur fait la taille d'un pointeur mais qu'en est t il déclaré comme extern ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    un pointeur déclaré par extern, static, auto ou autre est un pointeur; il a la taille d'un pointeur.
    extern ne sert qu'à indiquer au linker qu'il est dans autre unité, il n'y a à l'utilisation même pas une copie.
    Donc l'utilisation de gui->notebook_editor provoque :
    • lecture du pointeur gui
    • ajout de l'offset notebook_editor
    • lecture du pointeur à l"offset, cad gui->notebook_editor

    En créant un pointeur global
    gui_notebook_editor = gui->notebook_editor; il ne reste que
    • lecture du pointeur gui_notebook_editor
    En compilation optimisée, les deux instructions gagnées n'utilisent un seul cycle sur quasi-tous les processeurs, donc pas vraiment utile selon moi.

  5. #5
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci pour cette réponse technique qui m'aide a voir ce que je voulait savoir et pour votre aide a vous tous.

    Donc a ton avis pas besoin de gagner le calcule de l'offset au prix d'une variable globale de plus.

  6. #6
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut Comment ont fait alors ???
    Citation Envoyé par Luke spywoker
    Sinon je n'ai aucun problème avec mon programme et mes variables globales
    Tu n'en as pas parce que ton compilateur est « sympa » (ou pas) et qu'il considère la définition de gui inclue plusieurs fois comme une déclaration. Le mode par défaut de l'éditeur de liens doit faire le reste. C'est toutefois une erreur d'après la norme.
    Bon merci, mais si je veut pas que mon compilateur soit `sympa' et respecter la norme y a t-il une options a passer a gcc a fin qu'il soit moins permissif ?




    Je résume j'ai un fichier d'en-tête qui `déclare' mes variables globales comme la variable de type GUI que j'inclus dans les fichiers *.c ou j'ai besoin de ces variables globales.

    Puis je les déclares comme extern dans les fonctions ou j'en ai besoin.

    Je compiles plusieurs fichiers objet comme cela. Comment fait ont alors pour le faire correctement (ou plutôt selon la norme) ?

    Car pour moi c'est déjà un petit exploit de compiler plusieurs fichiers objets en référençant toujours la même instance de variable globale...

    PS: je l'ai dit plus haut il ne m'est pas toujours possible de passer en argument avec GTK+3.0.




    Concernant make je ne comprends pas pas trop:

    Parmi tous les langages imbitables sortis des méandres des cerveaux névrosés des programmeurs, celui de Make est bien l'un des pires. Peu lisible, « error-prone »... De plus il n'est pas normalisé - contrairement à un système de build de haut niveau - ce qui signifie que tu n'as aucune garantie que ton makefile fonctionne ailleurs que sur ta distribution de développement.
    Car les autotools se basent sur l'outil make, par le biais automake, sans compter ceux que je connais pas (Cmake) ???

    J'ai lu le GNU Coding Standards et je pense que l'équipe de Stallman a écrit ce(s) document(s) afin de mettre en place des conventions afin que justement le programme soit le plus portable possible (je parle du système de build).

    Mais je vous rassure mes projets n'ont pas besoins des autotools pour la phase de développement, et même:
    Distribuer un Makefile.in écrit a la mains est dans la norme du GNU Coding standards, cela va avec la taille de mes projets et un peu de bon sens dans l'écriture du Makefile.

    J'attends vos réponses éclairées avec impatience.

    Mouarfs je vient de relire tout le poste et je me demande si j'inclue la définition aussi ou seulement dans le fichier main.c...

  7. #7
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Citation Envoyé par Luke spywoker Voir le message
    D'accord nous ne somme plus en 1988,

    mais je pense qu'il faut connaître la syntaxe des Makefile avant d'utiliser les autotools.

    Je dit ça empiriquement (par expérience) car j'ai appris les autotools sans connaître le fond de l'outil make, sur lequel sont basé grand nombre de projets.

    Et ça ne m'a pas vraiment réussis car avant de lire le GNU manual de make, je comprenait mal les autotools.

    Et ça tombe bien que tu me dise cela car c'est pour générer un Makefile que je pose la question dessus.

    Je pense qu'il faut apprendre a lire et a écrire avant de générer des données, car l'ont dit que l'ordi est une extension de son cerveau... a méditer.
    Certes, et c'est tout à ton honneur de chercher à comprendre le fonctionnement des choses si tu en as le temps et la motivation. Je te disais cela dans une optique de productivité, car tu dis que ton projet atteint une taille respectable. Parfois on veut simplement que les choses « marchent » afin de pouvoir se consacrer à un autre aspect du problème.

    Parmi tous les langages imbitables sortis des méandres des cerveaux névrosés des programmeurs, celui de Make est bien l'un des pires. Peu lisible, « error-prone »... De plus il n'est pas normalisé - contrairement à un système de build de haut niveau - ce qui signifie que tu n'as aucune garantie que ton makefile fonctionne ailleurs que sur ta distribution de développement.


    Citation Envoyé par Luke spywoker Voir le message
    Sinon je n'ai aucun problème avec mon programme et mes variables globales
    Tu n'en as pas parce que ton compilateur est « sympa » (ou pas) et qu'il considère la définition de gui inclue plusieurs fois comme une déclaration. Le mode par défaut de l'éditeur de liens doit faire le reste. C'est toutefois une erreur d'après la norme.


    Citation Envoyé par Luke spywoker Voir le message
    mais je voulait simplement savoir si il est plus court d'écrire un pointeur de GtkWidget au lieu d'un pointeur sur une structure de GtkWidget déclaré comme extern ?

    Mais sûrement que un pointeur fait la taille d'un pointeur mais qu'en est t il déclaré comme extern ?
    extern sert - grosso modo - à changer une définition en déclaration. Il n'y a aucune incidence sur la nature de la variable déclarée. Si c'est écrire gui-> qui te fatigue, déclares une variable locale pour représenter l'objet pointé ou crées un #define.

    À noter qu'il peut-être nécessaire de décorréler le code de la variable globale pour le rendre plus générique. Par exemple, tes fonctions pourraient ainsi intervenir sur un widget - passé en paramètre, donc - qui ne fait pas partie de l'instance principale de GUI (je ne sais pas si ça a un intérêt).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 14/10/2009, 10h52
  2. variable globale definie dans un .js externe
    Par master_kb2 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 05/04/2008, 17h58
  3. STL List et variable globale (extern)
    Par flipper203 dans le forum SL & STL
    Réponses: 9
    Dernier message: 04/07/2006, 14h20
  4. Utilisation variable globale, extern...
    Par mamok dans le forum MFC
    Réponses: 3
    Dernier message: 29/03/2006, 10h50
  5. variable global fichier externe?
    Par molesqualeux dans le forum C
    Réponses: 4
    Dernier message: 01/02/2006, 16h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo