Extern et register en C
Fermé
mickmac
Messages postés
413
Date d'inscription
jeudi 25 août 2011
Statut
Membre
Dernière intervention
15 août 2019
-
11 déc. 2012 à 10:55
totof31 Messages postés 163 Date d'inscription lundi 29 octobre 2012 Statut Membre Dernière intervention 30 avril 2013 - 15 déc. 2012 à 20:19
totof31 Messages postés 163 Date d'inscription lundi 29 octobre 2012 Statut Membre Dernière intervention 30 avril 2013 - 15 déc. 2012 à 20:19
A voir également:
- Extern et register en C
- Analyser et réparer disque dur externe - Guide
- 'Ls' n’est pas reconnu en tant que commande interne ou externe, un programme exécutable ou un fichier de commandes. - Forum Windows
- Dll register server introuvable - Forum Windows 10
- Microsoft register server - Forum Windows 8 / 8.1
- Disque dur externe compatible mac et pc sans formatage - Forum MacOS
5 réponses
totof31
Messages postés
163
Date d'inscription
lundi 29 octobre 2012
Statut
Membre
Dernière intervention
30 avril 2013
74
11 déc. 2012 à 12:00
11 déc. 2012 à 12:00
Salut,
extern permet de donner le prototype d'une fonction ou le type d'une variable, lorsque celle-ci ou celui-ci n'est pas déclaré dans le fichier .c courant/
Ainsi, quand dans un .c on appelle cette fonction ou cette variable, le compilateur connait le type des arguments, de la valeur de retour, ou de la variable, et il peut tester/valider... tous ces paramètres.
En l'absence de "extern" il suppose que les paramètres passés lors de l'appel d'une fonction sont du bon type (il ne peut pas vérifier), et que la fonction retourne un int. Pour les variables, en général il sort en erreur.
register, c'est pour demander au compilateur d'affecter un registre à une variable (dans la limite du nombre de registres disponibles). Normalement, une variable est enregistrée en mémoire, et pas dans un registre. Avec ce mot clef, on espère ainsi avoir un accès rapide à la donnée.
extern permet de donner le prototype d'une fonction ou le type d'une variable, lorsque celle-ci ou celui-ci n'est pas déclaré dans le fichier .c courant/
Ainsi, quand dans un .c on appelle cette fonction ou cette variable, le compilateur connait le type des arguments, de la valeur de retour, ou de la variable, et il peut tester/valider... tous ces paramètres.
En l'absence de "extern" il suppose que les paramètres passés lors de l'appel d'une fonction sont du bon type (il ne peut pas vérifier), et que la fonction retourne un int. Pour les variables, en général il sort en erreur.
register, c'est pour demander au compilateur d'affecter un registre à une variable (dans la limite du nombre de registres disponibles). Normalement, une variable est enregistrée en mémoire, et pas dans un registre. Avec ce mot clef, on espère ainsi avoir un accès rapide à la donnée.
mickmac
Messages postés
413
Date d'inscription
jeudi 25 août 2011
Statut
Membre
Dernière intervention
15 août 2019
6
12 déc. 2012 à 12:03
12 déc. 2012 à 12:03
Ok merci bien
Et pour static pour une fonction(pour une variable je comprend) ça fait quoi?
As-tu un exemple?
Merci
Et pour static pour une fonction(pour une variable je comprend) ça fait quoi?
As-tu un exemple?
Merci
totof31
Messages postés
163
Date d'inscription
lundi 29 octobre 2012
Statut
Membre
Dernière intervention
30 avril 2013
74
12 déc. 2012 à 15:32
12 déc. 2012 à 15:32
Pour une fonction, static dit au compilateur que la fonction ne pourra pas être appelée à partir d'un autre .c
Selon le compilateur, il est même possible d'avoir plusieurs fonctions qui portent le même nom, du moment où elles sont chacune dans un .c différent. Ceci dit, ce n'est pas vraiment recommandé question maintenabilité.
Selon le compilateur, il est même possible d'avoir plusieurs fonctions qui portent le même nom, du moment où elles sont chacune dans un .c différent. Ceci dit, ce n'est pas vraiment recommandé question maintenabilité.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 841
12 déc. 2012 à 17:25
12 déc. 2012 à 17:25
Pour les variables, il y a deux utilisations de static selon qu'il soit utilisé en global ou en local (dans une fonction).
En global, totof31 a tout dit.
En local, cela signifiera que la variable sera persistante. C'est-à-dire que la variable ne sera pas détruire à la fin de la fonction.
En global, totof31 a tout dit.
En local, cela signifiera que la variable sera persistante. C'est-à-dire que la variable ne sera pas détruire à la fin de la fonction.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
totof31
Messages postés
163
Date d'inscription
lundi 29 octobre 2012
Statut
Membre
Dernière intervention
30 avril 2013
74
13 déc. 2012 à 11:46
13 déc. 2012 à 11:46
C'est très juste fiddy, merci pour cet ajout.
J'avais complètement zappé cet usage, car bossant dans l'embarqué depuis plus de 10 ans, il est tout simplement interdit par les règles de codage des différents projets rencontrés.
Ceci dit, voici un exemple :
Ainsi, compteur est initialisé à 0 lors du chargement de l'appli.
Il est incrémenté à chaque fois qu'on rentre dans la fonction, sans être remis à 0 ! Le "= 0" sert juste à donner sa valeur initiale.
J'avais complètement zappé cet usage, car bossant dans l'embarqué depuis plus de 10 ans, il est tout simplement interdit par les règles de codage des différents projets rencontrés.
Ceci dit, voici un exemple :
void ma_fonction(void) { static int compteur = 0; compteur++; ... }
Ainsi, compteur est initialisé à 0 lors du chargement de l'appli.
Il est incrémenté à chaque fois qu'on rentre dans la fonction, sans être remis à 0 ! Le "= 0" sert juste à donner sa valeur initiale.
mickmac
Messages postés
413
Date d'inscription
jeudi 25 août 2011
Statut
Membre
Dernière intervention
15 août 2019
6
13 déc. 2012 à 19:26
13 déc. 2012 à 19:26
Oui ça j'ai bien compris , c'est une variable qui est statque ça j'ai parfaitement compris, Ce que j'ai du mal à comprendre c'esr le role de static devant une définition de fonction .
D'après ce que tu me dis c'est que je bloque l'utilisation de la fonction à d'un fichier .c
C'est bien ça???
Merci
D'après ce que tu me dis c'est que je bloque l'utilisation de la fonction à d'un fichier .c
C'est bien ça???
Merci
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 841
13 déc. 2012 à 19:56
13 déc. 2012 à 19:56
totof31
D'ailleurs le =0 est facultatif. Par défaut, c'est initialisé à 0.
mickmac,
Oui c'est bien ça. Sans local, la fonction sera externe, elle pourra être appelée dans d'autre fichier pourvu qu'elle soit déclarée avant appel.
Avec static, la fonction ne pourra pas être appelée en dehors du fichier. L'intérêt principal est d'éviter les conflits de nom.
D'ailleurs le =0 est facultatif. Par défaut, c'est initialisé à 0.
mickmac,
Oui c'est bien ça. Sans local, la fonction sera externe, elle pourra être appelée dans d'autre fichier pourvu qu'elle soit déclarée avant appel.
Avec static, la fonction ne pourra pas être appelée en dehors du fichier. L'intérêt principal est d'éviter les conflits de nom.
totof31
Messages postés
163
Date d'inscription
lundi 29 octobre 2012
Statut
Membre
Dernière intervention
30 avril 2013
74
14 déc. 2012 à 09:40
14 déc. 2012 à 09:40
D'ailleurs le =0 est facultatif. Par défaut, c'est initialisé à 0.
Oui, ça semble vrai aujourd'hui, c'est d'ailleurs dans les normes C90 et C99, mais :
- ça ne l'était pas avec les premiers compilateurs C avec lesquels j'ai travaillé, qui étaient pourtant tagués ANSI pour certains ! (Ouais, je sais, je me fais vieux ;-) )
- ça ne dépend pas que du compilateur, mais aussi de l'OS. Ainsi pour une cible embarquée (et je radote également...) sans OS ou avec un OS spécifique, il n'y a pas toujours d'initialisation de la RAM, ou alors elle est initialisée avec un motif (genre CAFEFECA, DEADBEEF...) afin par exemple de tracer l'utilisation de la mémoire avec des outils spécifiques...
Tout ça pour dire (ça n'engage que moi) que même sur une machine moderne, je ne laisse jamais une variable non initialisée.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 841
14 déc. 2012 à 12:30
14 déc. 2012 à 12:30
Je tiens à apporter des précisions (et des questions) :
D'ailleurs le =0 est facultatif. Par défaut, c'est initialisé à 0.
Quand, je dis ça je parle bien des variables "static" (d'ailleurs cela s'applique également aux variables globales). Mais pour les variables automatiques, il est nécessaire d'initialiser explicitement.
Après, il faut savoir comment cela se traduit dans l'exécutable final.
Une variable statique non initialisée à 0 sera mise dans le .bss (qui est prédéfini à 0). Alors que si tu l'initialises la variable statique sera mise dans le.data (sauf si optimisation bien sûr). Du coup la taille de l'exécutable grossira en même temps que le .data (ce qui ne sera pas le cas avec le .bss).
Donc dans ton cas (embarqué), il est donc intéressant de ne pas initialiser explicitement les variables statiques (et globales) à 0. As-tu déjà trouvé un contre-exemple ???
Sinon pour l'embarqué pourquoi n'utilises-tu pas de variables "static" ou "global" ? Cela est moins performant, certes mais produit un code moins gourmand. En effet les variables automatiques sont remplacées par des pointeurs dans la pile alors que les variables "static" et "global" sont à des adresses fixes.
D'ailleurs le =0 est facultatif. Par défaut, c'est initialisé à 0.
Quand, je dis ça je parle bien des variables "static" (d'ailleurs cela s'applique également aux variables globales). Mais pour les variables automatiques, il est nécessaire d'initialiser explicitement.
Après, il faut savoir comment cela se traduit dans l'exécutable final.
Une variable statique non initialisée à 0 sera mise dans le .bss (qui est prédéfini à 0). Alors que si tu l'initialises la variable statique sera mise dans le.data (sauf si optimisation bien sûr). Du coup la taille de l'exécutable grossira en même temps que le .data (ce qui ne sera pas le cas avec le .bss).
Donc dans ton cas (embarqué), il est donc intéressant de ne pas initialiser explicitement les variables statiques (et globales) à 0. As-tu déjà trouvé un contre-exemple ???
Sinon pour l'embarqué pourquoi n'utilises-tu pas de variables "static" ou "global" ? Cela est moins performant, certes mais produit un code moins gourmand. En effet les variables automatiques sont remplacées par des pointeurs dans la pile alors que les variables "static" et "global" sont à des adresses fixes.
Donc dans ton cas (embarqué), il est donc intéressant de ne pas initialiser explicitement les variables statiques (et globales) à 0.
C'est exactement ça. Dans les calculateurs automobile, où on gratte le moindre centime et où les soft logent au chausse-pied, ça permet d'économiser plusieurs dizaines de ko de RAM.
As-tu déjà trouvé un contre-exemple ???
Oui, il y a un revers pour les variables qui doivent être initialisée à autre chose que zéro. Ces variables sont initialisées par une fonction d'initialisation dédiée pour chaque module. Ca ne prend donc pas de place en section .data mais ça ajoute du code. Dans les règles de design, on fait donc en sorte qu'il y ait le moins de données possible de ce type.
Sinon pour l'embarqué pourquoi n'utilises-tu pas de variables "static" ou "global" ?
Euh, je me suis peut-être mal exprimé mais je ne crois pas avoir dit ça...
La seule chose qui est interdite, ce sont les variables static à l'intérieur d'une fonction, car il n'y a pas de mécanisme pour les initialiser lors du startup. Mais sinon j'utilise évidemment des variables static (hors fonction), globales ou automatiques.
Cela est moins performant, certes mais produit un code moins gourmand. En effet les variables automatiques sont remplacées par des pointeurs dans la pile alors que les variables "static" et "global" sont à des adresses fixes.
Là je suis désolé mais je ne n'arrive pas bien à suivre ton idée. Tu sembles dire que les variables automatiques sont moins performantes que les variables globales mais produisent un code moins gourmand, c'est ça ? Ou l'inverse ?...
Ca ne rejoint pas vraiment mon expérience, car :
- pour accéder à une variable globale ou static hors fonction, il faut au préalable charger un registre avec l'adresse de la variable, puis faire un load/store (entre 2 et 3 instructions assembleur selon la cible, voire 4).
- pour accéder à une variable automatique, il suffit de faire un load/store avec un offset par rapport au pointeur de pile (en général 1 instruction assembleur suffit), car le pointeur de pile est dans un registre dédié donc toujours disponible (je ne connais pas de contre exemple). De plus, on utilise généralement pour ces variables le mot clef register. Ainsi, la variable n'est même pas en RAM, on y accède rapidement (pas d'accès bus) avec une seule instruction assembleur.
Même sans register, l'utilisation de variables auto est donc à la fois plus économique et plus performant.
Après, on peut imaginer que ça puisse aussi varier en fonction du niveau d'optimisation demandé/réalisé par le compilateur...