J'ai vu le mot staticutilisé à différents endroits dans le code C; est-ce comme une fonction / classe statique en C # (où l'implémentation est partagée entre les objets)?
Quelle est la raison de supprimer "dans un programme C" à la fin du titre, @Lundin? Il est légèrement redondant en présence de la balise c , mais il me permet de voir la catégorisation plus rapidement, sans inspecter les balises. Cette redondance est très confortable lorsque j'atteins la question dans une direction qui peut également contenir des questions sur d'autres langues, par exemple la recherche statique ou Google.
Palec
5
@Palec Il existe une politique SO selon laquelle les éléments présents dans la liste de balises sont redondants dans le titre. Le site ajoutera automatiquement C au site Web réel. Un Google pour "C statique" donne cette réponse comme top hit. La raison pour laquelle cela a été modifié est que cette question fait maintenant partie de la FAQ sur le langage SO C et que tous les messages ajoutés sont un peu peaufinés.
Lundin
1
@Lundin Je préfère garder "C" dans le titre, car SO n'ajoute qu'une seule balise au titre (la plus courante?). Que se passe-t-il si un jour la "syntaxe" atteint plus de questions que C (puisque c'est une chose cross-language)? Je préfère utiliser le comportement explicite :-) Edit: ah mais il y a une méta-question disant autrement: meta.stackexchange.com/questions/19190/…
Une variable statique à l'intérieur d'une fonction conserve sa valeur entre les invocations.
Une variable globale statique ou une fonction est "vue" uniquement dans le fichier dans lequel elle est déclarée
(1) est le sujet le plus étranger si vous êtes un débutant, alors voici un exemple:
#include<stdio.h>void foo(){int a =10;staticint sa =10;
a +=5;
sa +=5;
printf("a = %d, sa = %d\n", a, sa);}int main(){int i;for(i =0; i <10;++i)
foo();}
Cela imprime:
a =15, sa =15
a =15, sa =20
a =15, sa =25
a =15, sa =30
a =15, sa =35
a =15, sa =40
a =15, sa =45
a =15, sa =50
a =15, sa =55
a =15, sa =60
Cela est utile dans les cas où une fonction doit conserver un état entre les invocations et où vous ne souhaitez pas utiliser de variables globales. Attention cependant, cette fonctionnalité doit être utilisée avec parcimonie - elle rend votre code non thread-safe et plus difficile à comprendre.
(2) Est largement utilisé comme fonction de "contrôle d'accès". Si vous avez un fichier .c implémentant certaines fonctionnalités, il expose généralement seulement quelques fonctions "publiques" aux utilisateurs. Le reste de ses fonctions doit être créé static, afin que l'utilisateur ne puisse pas y accéder. Il s'agit d'encapsulation, une bonne pratique.
Dans le langage de programmation C, static est utilisé avec des variables et des fonctions globales pour définir leur portée sur le fichier conteneur. Dans les variables locales, statique est utilisé pour stocker la variable dans la mémoire allouée statiquement au lieu de la mémoire allouée automatiquement. Bien que le langage ne dicte pas la mise en œuvre de l'un ou l'autre type de mémoire, la mémoire allouée statiquement est généralement réservée dans le segment de données du programme au moment de la compilation, tandis que la mémoire allouée automatiquement est normalement implémentée comme une pile d'appels transitoires.
Et pour répondre à votre deuxième question, ce n'est pas comme en C #.
En C ++, cependant, staticest également utilisé pour définir des attributs de classe (partagés entre tous les objets de la même classe) et des méthodes. En C, il n'y a pas de classes, donc cette fonctionnalité n'est pas pertinente.
Pax, l'OP ne connaît pas la statique, alors vous proposez de le plonger dans la différence entre les unités de compilation et les fichiers? :-)
Eli Bendersky
138
Une unité de compilation est un fichier unique que le compilateur voit. Votre fichier .c peut inclure d'autres fichiers .c, mais après que le préprocesseur a trié les inclusions, le compilateur ne voit finalement qu'une seule "unité de compilation".
Eli Bendersky
81
@robUK: le compilateur ne connaît même pas les fichiers .h - ceux-ci sont combinés dans les fichiers .c du préprocesseur. Donc oui, vous pouvez dire que le fichier .c, avec tous les en-têtes inclus, est une seule unité de compilation.
Eli Bendersky
6
@TonyD c'est peut-être déroutant, mais c'est ainsi que fonctionne la compilation. Il peut généralement s'agir d'un .cet de plusieurs fichiers d'en-tête, mais le diable est toujours dans ce qui n'est pas typique.
peterph
7
@TonyD Le compilateur fait la compilation. Le préprocesseur effectue le prétraitement. Appeler la chaîne d'outils «le compilateur» ne change pas ce que c'est ni ce qu'il fait.
Miles Rout du
231
Il y a une autre utilisation non couverte ici, qui fait partie d'une déclaration de type tableau en tant qu'argument d'une fonction:
int someFunction(char arg[static10]){...}
Dans ce contexte, cela spécifie que les arguments passés à cette fonction doivent être un tableau de type charcontenant au moins 10 éléments. Pour plus d'informations voir ma question ici .
Je ne pensais pas que C avait des arguments de tableau? Linus Torvalds s'énerve avec colère contre les gens qui font ça.
suprjami
13
@jamieb: C n'a pas d' arguments de tableau, mais ce moyen de syntaxe spécifiques qu'attend la fonction arg[0]jusqu'à arg[9]avoir des valeurs ( ce qui implique également que la fonction n'accepte pas un pointeur NULL). Les compilateurs pourraient utiliser ces informations d'une manière ou d'une autre pour l'optimisation, et les analyseurs statiques peuvent utiliser ces informations pour s'assurer que la fonction ne reçoit jamais de pointeur nul (ou, si elle peut le dire, un tableau avec moins d'éléments que spécifié).
dreamlax
19
@Qix - C'était une nouvelle signification surchargée donnée staticdans C99. Il a plus de dix ans et demi, mais tous les auteurs de compilateurs n'ont pas embrassé toutes les fonctionnalités de C99 - donc C99 dans son ensemble reste largement inconnu.
Happy Green Kid Naps
@suprjami Je ne suis pas sûr à 100% de ce que vous entendez par "arguments de tableau" , mais si vous voulez dire int arr[n];, alors c'est un VLA (tableau de longueur variable) , qui a été ajouté en C99. C'est ce que vous vouliez dire?
RastaJedi
170
Réponse courte ... cela dépend.
Les variables locales définies statiquement ne perdent pas leur valeur entre les appels de fonction. En d'autres termes, ce sont des variables globales, mais limitées à la fonction locale dans laquelle elles sont définies.
Les variables globales statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.
Les fonctions statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.
Ainsi, «fonction statique» et «fonction privée» signifient la même chose? De même, les "variables globales statiques" et les "variables globales privées" sont-elles la même chose?
user1599964
40
Il s'agit de C. Il n'y a pas de privé / public en C.
chris
19
@ user1599964 bien qu'il n'y privateen ait pas en C, votre analogie est bonne: statique rend les choses "privées" à un fichier donné. Et les fichiers en C sont souvent mappés aux classes en C ++.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
67
Exemple de portée variable multi-fichiers
Ici, j'illustre comment statique affecte la portée des définitions de fonction sur plusieurs fichiers.
ac
#include<stdio.h>/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
/programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*//*int i = 0;*//* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 *//*int i;*//* OK: extern. Will use the one in main. */externint i;/* OK: only visible to this file. */staticint si =0;void a(){
i++;
si++;
puts("a()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");}
m()
i =1
si =1
m()
i =2
si =2
a()
i =3
si =1
a()
i =4
si =2
Interprétation
il y a deux variables distinctes pour si , une pour chaque fichier
il existe une seule variable partagée pour i
Comme d'habitude, plus la portée est petite, mieux c'est, donc toujours déclarer des variables static si vous le pouvez.
En programmation C, les fichiers sont souvent utilisés pour représenter des "classes", et static variables représentent des membres statiques privés de la classe.
Ce que les normes en disent
C99 N1256 draft 6.7.1 "Storage-class specifiers" dit questatic s'agit d'un "stockage-class specifier".
6.2.2 / 3 "Liens d'identifiants" dit staticimpliqueinternal linkage :
Si la déclaration d'un identificateur de portée de fichier pour un objet ou une fonction contient le spécificateur de classe de stockage statique, l'identificateur a une liaison interne.
et 6.2.2 / 2 dit que internal linkagese comporte comme dans notre exemple:
Dans l'ensemble d'unités de traduction et de bibliothèques qui constitue un programme entier, chaque déclaration d'un identifiant particulier avec liaison externe désigne le même objet ou la même fonction. Au sein d'une unité de traduction, chaque déclaration d'un identifiant avec lien interne dénote le même objet ou fonction.
où "unité de traduction est un fichier source après le prétraitement.
Comment GCC l'implémente-t-il pour ELF (Linux)?
Avec le STB_LOCAL reliure.
Si nous compilons:
int i =0;staticint si =0;
et démontez la table des symboles avec:
readelf -s main.o
la sortie contient:
Num:ValueSizeTypeBindVisNdxName5:00000000000000044 OBJECT LOCAL DEFAULT 4 si
10:00000000000000004 OBJECT GLOBAL DEFAULT 4 i
donc la liaison est la seule différence significative entre eux. Valueest juste leur décalage dans le.bss section, nous nous attendons donc à ce qu'il diffère.
STB_LOCAL Les symboles locaux ne sont pas visibles en dehors du fichier objet contenant leur définition. Des symboles locaux du même nom peuvent exister dans plusieurs fichiers sans interférer les uns avec les autres
ce qui en fait un choix parfait pour représenter static .
Les variables sans statique sont STB_GLOBAL, et la spécification dit:
Lorsque l'éditeur de liens combine plusieurs fichiers d'objets déplaçables, il n'autorise pas plusieurs définitions de symboles STB_GLOBAL avec le même nom.
ce qui est cohérent avec les erreurs de liaison sur plusieurs définitions non statiques.
Si nous augmentons l'optimisation avec -O3, le sisymbole est entièrement supprimé de la table des symboles: il ne peut en aucun cas être utilisé de l'extérieur. TODO pourquoi garder les variables statiques sur la table des symboles quand il n'y a pas d'optimisation? Peuvent-ils être utilisés pour quelque chose? Peut-être pour le débogage.
En C ++, vous souhaiterez peut-être utiliser des espaces de noms anonymes au lieu de statiques, ce qui produit un effet similaire, mais masque en outre les définitions de type: espaces de noms sans nom / anonymes vs fonctions statiques
La fonction retournerait 1, 2, 3, etc. --- la variable n'est pas sur la pile.
ac:
staticint foo(){}
Cela signifie que cette fonction n'a de portée que dans ce fichier. Donc, ac et bc peuvent avoir des foo()s différents , et foo n'est pas exposé aux objets partagés. Donc, si vous avez défini foo en ac, vous ne pouvez pas y accéder depuis b.cou depuis d'autres endroits.
Dans la plupart des bibliothèques C, toutes les fonctions "privées" sont statiques et la plupart "publiques" ne le sont pas.
+1 pour mentionner x pas sur la pile ou le tas. C'est sur l'espace mémoire statique.
Gob00st
1
@ Gob00st espace mémoire statique? vous vouliez dire "segment de données" ...?
Yousha Aleayoub
24
Les gens continuent à dire que «statique» en C a deux significations. Je propose une autre façon de le voir qui lui donne un sens unique:
L'application de «statique» à un élément force cet élément à avoir deux propriétés: (a) il n'est pas visible en dehors de la portée actuelle; (b) Elle est persistante.
La raison pour laquelle il semble avoir deux significations est que, en C, chaque élément auquel «statique» peut être appliqué possède déjà l'une de ces deux propriétés , il semble donc que cet usage particulier n'implique que l'autre.
Par exemple, considérez les variables. Les variables déclarées en dehors des fonctions ont déjà une persistance (dans le segment de données), donc appliquer 'statique' ne peut que les rendre non visibles en dehors de la portée actuelle (unité de compilation). Au contraire, les variables déclarées à l'intérieur des fonctions ont déjà une non-visibilité en dehors de la portée (fonction) actuelle, donc l'application de «statique» ne peut que les rendre persistantes.
Appliquer «statique» aux fonctions revient à l'appliquer aux variables globales - le code est nécessairement persistant (au moins dans le langage), donc seule la visibilité peut être modifiée.
REMARQUE: ces commentaires s'appliquent uniquement à C. En C ++, appliquer «statique» aux méthodes de classe donne vraiment au mot-clé une signification différente. De même pour l'extension d'argument tableau C99.
Votre (a) est au mieux redondant. Aucune variable quelle qu'elle soit n'est visible en dehors de sa portée. C'est simplement la définition de la portée. Ce que vous voulez dire est appelé liaison dans la norme C. staticdonne un lien interne à un identifiant.
Jens
16
De Wikipédia:
Dans le langage de programmation C, statique est utilisé avec des variables et des fonctions globales pour définir leur portée sur le fichier conteneur. Dans les variables locales, statique est utilisé pour stocker la variable dans la mémoire allouée statiquement au lieu de la mémoire allouée automatiquement. Bien que le langage ne dicte pas la mise en œuvre de l'un ou l'autre type de mémoire, la mémoire allouée statiquement est généralement réservée dans le segment de données du programme au moment de la compilation, tandis que la mémoire allouée automatiquement est normalement implémentée comme une pile d'appels transitoires.
static signifie des choses différentes dans des contextes différents.
Vous pouvez déclarer une variable statique dans une fonction C. Cette variable n'est visible que dans la fonction mais elle se comporte comme une globale dans la mesure où elle n'est initialisée qu'une seule fois et conserve sa valeur. Dans cet exemple, chaque fois que vous appelez foo(), un nombre croissant sera imprimé. La variable statique n'est initialisée qu'une seule fois.
void foo (){staticint i =0;
printf("%d", i); i++}
Une autre utilisation de statique est lorsque vous implémentez une fonction ou une variable globale dans un fichier .c mais que vous ne voulez pas que son symbole soit visible en dehors de celui .objgénéré par le fichier. par exemple
Si vous déclarez une variable dans une fonction statique, sa valeur ne sera pas stockée dans la pile d'appels de fonction et sera toujours disponible lorsque vous appellerez à nouveau la fonction.
Si vous déclarez une variable globale statique, sa portée sera limitée au sein du fichier dans lequel vous l'avez déclarée. Ceci est légèrement plus sûr qu'un global régulier qui peut être lu et modifié tout au long de votre programme.
Je déteste répondre à une vieille question, mais je ne pense pas que quiconque ait mentionné comment K&R l'explique dans la section A4.1 du "Langage de programmation C".
En bref, le mot statique est utilisé avec deux significations:
Statique est l'une des deux classes de stockage (l'autre étant automatique). Un objet statique conserve sa valeur entre les invocations. Les objets déclarés en dehors de tous les blocs sont toujours statiques et ne peuvent pas être rendus automatiques.
Mais, lorsque le staticmot - clé (grand accent mis sur son utilisation dans le code en tant que mot-clé) est utilisé avec une déclaration, il donne à cet objet un lien interne de sorte qu'il ne peut être utilisé que dans cette unité de traduction. Mais si le mot-clé est utilisé dans une fonction, il change la classe de stockage de l'objet (l'objet ne serait de toute façon visible que dans cette fonction). L'opposé de statique est le externmot - clé, qui donne un lien externe à un objet.
Peter Van Der Linden donne ces deux significations dans "Expert C Programming":
A l'intérieur d'une fonction, conserve sa valeur entre les appels.
Au niveau de la fonction, visible uniquement dans ce fichier.
Il y a une troisième classe de stockage, inscrivez-vous . Certaines personnes plaident également pour une quatrième classe de stockage, allouée , pour le stockage retourné par malloc et ses amis.
Jens
@Jens 'register' n'est qu'un indice pour le compilateur; le stockage du registre ne peut pas être appliqué à partir de la source C. Je ne considérerais donc pas cela comme une classe de stockage.
GermanNerd
1
@GermanNerd J'ai bien peur que la norme ISO C soit en désaccord avec votre point de vue, car elle crée clairement registerun spécificateur de classe de stockage (C99 6.7.1 Spécificateurs de classe de stockage). Et c'est plus qu'un simple indice, par exemple, vous ne pouvez pas appliquer l'opérateur address-of &sur un objet avec une classe de stockage, registerque le compilateur alloue ou non un registre.
Jens
@Jens Merci de m'avoir rappelé &. J'ai peut-être fait trop de C ++ ..... Quoi qu'il en soit, alors que "register" est un spécificateur de classe de stockage, en réalité, le compilateur créera probablement le même code machine pour le spécificateur (inutile) "auto" que pour le "registre" 'spécificateur. Donc, la seule chose qui reste est la restriction au niveau du code source de ne pas pouvoir prendre une adresse. BTW, cette petite discussion m'a amené à trouver un bug dans Netbeans; depuis ma dernière mise à jour, il utilise par défaut la chaîne d'outils g ++ sur les nouveaux projets C!
GermanNerd
6
En C, statique a deux significations, selon l'étendue de son utilisation. Dans la portée globale, lorsqu'un objet est déclaré au niveau du fichier, cela signifie que cet objet n'est visible que dans ce fichier.
À toute autre portée, il déclare un objet qui conservera sa valeur entre les différents moments où la portée particulière est entrée. Par exemple, si un int est supprimé dans une procédure:
void procedure(void){staticint i =0;
i++;}
la valeur de «i» est initialisée à zéro lors du premier appel à la procédure et la valeur est conservée à chaque appel ultérieur de la procédure. si «i» était imprimé, il produirait une séquence de 0, 1, 2, 3, ...
Il est important de noter que les variables statiques dans les fonctions sont initialisées à la première entrée dans cette fonction et persistent même après la fin de leur appel; en cas de fonctions récursives, la variable statique n'est initialisée qu'une seule fois et persiste également pendant tous les appels récursifs et même après la fin de l'appel de la fonction.
Si la variable a été créée en dehors d'une fonction, cela signifie que le programmeur ne peut utiliser la variable que dans le fichier source, la variable a été déclarée.
Cette variable n'est alors visible que depuis ce fichier. La variable ne peut pas être exportée ailleurs.
Si vous déclarez à l'intérieur d'une fonction, la valeur de la variable gardera sa valeur à chaque appel de la fonction.
Une fonction statique ne peut pas être exportée de l'extérieur du fichier. Donc dans un *.cfichier, vous cachez les fonctions et les variables si vous les déclarez statiques.
Les variables statiques en C ont la durée de vie du programme.
S'ils sont définis dans une fonction, ils ont une portée locale, c'est-à-dire qu'ils ne sont accessibles qu'à l'intérieur de ces fonctions. La valeur des variables statiques est préservée entre les appels de fonction.
Dans le programme ci-dessus, var est stocké dans le segment de données. Sa durée de vie est l'ensemble du programme C.
Après l'appel de fonction 1, vardevient 2. Après l'appel de fonction 2, vardevient 3.
La valeur de varn'est pas détruite entre les appels de fonctions.
S'il y varavait entre une variable non statique et locale, il serait stocké dans le segment de pile dans le programme C. Étant donné que le cadre de pile de la fonction est détruit après le retour de la fonction, la valeur de varest également détruite.
Les variables statiques initialisées sont stockées dans le segment de données du programme C tandis que celles non initialisées sont stockées dans le segment BSS.
Une autre information sur statique: si une variable est globale et statique, elle a la durée de vie du programme C, mais elle a une portée de fichier. Il n'est visible que dans ce fichier.
Pour essayer ceci:
file1.c
staticint x;int main(){
printf("Accessing in same file%d", x):}
file2.c
externint x;
func(){
printf("accessing in different file %d",x);// Not allowed, x has the file scope of file1.c}
run gcc -c file1.c
gcc -c file2.c
Essayez maintenant de les lier en utilisant:
gcc -o output file1.o file2.o
Cela donnerait une erreur de l'éditeur de liens car x a la portée de fichier de file1.c et l'éditeur de liens ne pourrait pas résoudre la référence à la variable x utilisée dans file2.c.
Je comprends que les données sont persistantes, ce qui signifie qu'elles ne seront pas perdues après chaque appel de fonction, mais pourquoi ne static int var = 1;changez-vous pas la valeur à un à chaque fois
Eames
3
Une variable statique est une variable spéciale que vous pouvez utiliser dans une fonction. Elle enregistre les données entre les appels et ne les supprime pas entre les appels. Par exemple:
void func(){staticint count;// If you don't declare its value, the value automatically initializes to zero
printf("%d, ", count);++count;}void main(){while(true){
func();}}
Une valeur de variable statique persiste entre différents appels de fonction et sa portée est limitée au bloc local une variable statique initialise toujours avec la valeur 0
(1) Variables locales déclarées static: allouées dans le segment de données au lieu de la pile. Sa valeur est conservée lorsque vous appelez à nouveau la fonction.
(2) Variables ou fonctions globales déclarées static: unité de compilation extérieure invisible (c'est-à-dire sont des symboles locaux dans la table des symboles lors de la liaison).
Les variables statiques ont la propriété de conserver leur valeur même lorsqu'elles sont hors de leur portée! Par conséquent, les variables statiques conservent leur valeur précédente dans leur étendue précédente et ne sont pas initialisées à nouveau dans la nouvelle étendue.
Regardez ceci par exemple - Une variable int statique reste en mémoire pendant l'exécution du programme. Une variable normale ou automatique est détruite lorsqu'un appel de fonction où la variable a été déclarée est terminé.
Comme 1 reste dans la mémoire car il a été déclaré statique
Les variables statiques (comme les variables globales) sont initialisées à 0 si elles ne sont pas initialisées explicitement. Par exemple, dans le programme ci-dessous, la valeur de x est imprimée comme 0, tandis que la valeur de y est quelque chose d'ordure. Voir ceci pour plus de détails.
Dans la programmation C, staticest un mot-clé réservé qui contrôle à la fois la durée de vie et la visibilité. Si nous déclarons une variable statique dans une fonction, elle ne sera visible que dans cette fonction. Dans cette utilisation, la durée de vie de cette variable statique commencera lors d'un appel de fonction et sera détruite après l'exécution de cette fonction. vous pouvez voir l'exemple suivant:
Parce que dès que nous appelons la fonction, elle initialise le count = 0. Et pendant que nous l'exécutons, counterFunctionil détruira la variable de comptage.
> Le programme ci-dessus nous donnera cette sortie: Première sortie du compteur = 1 Deuxième sortie du compteur = 1 <Pas vrai. Les variables statiques ne sont initialisées qu'une seule fois. La sortie sera donc 1, puis 2, et ainsi de suite.
Réponses:
(1) est le sujet le plus étranger si vous êtes un débutant, alors voici un exemple:
Cela imprime:
Cela est utile dans les cas où une fonction doit conserver un état entre les invocations et où vous ne souhaitez pas utiliser de variables globales. Attention cependant, cette fonctionnalité doit être utilisée avec parcimonie - elle rend votre code non thread-safe et plus difficile à comprendre.
(2) Est largement utilisé comme fonction de "contrôle d'accès". Si vous avez un fichier .c implémentant certaines fonctionnalités, il expose généralement seulement quelques fonctions "publiques" aux utilisateurs. Le reste de ses fonctions doit être créé
static
, afin que l'utilisateur ne puisse pas y accéder. Il s'agit d'encapsulation, une bonne pratique.Citant Wikipédia :
Et pour répondre à votre deuxième question, ce n'est pas comme en C #.
En C ++, cependant,
static
est également utilisé pour définir des attributs de classe (partagés entre tous les objets de la même classe) et des méthodes. En C, il n'y a pas de classes, donc cette fonctionnalité n'est pas pertinente.la source
.c
et de plusieurs fichiers d'en-tête, mais le diable est toujours dans ce qui n'est pas typique.Il y a une autre utilisation non couverte ici, qui fait partie d'une déclaration de type tableau en tant qu'argument d'une fonction:
Dans ce contexte, cela spécifie que les arguments passés à cette fonction doivent être un tableau de type
char
contenant au moins 10 éléments. Pour plus d'informations voir ma question ici .la source
arg[0]
jusqu'àarg[9]
avoir des valeurs ( ce qui implique également que la fonction n'accepte pas un pointeur NULL). Les compilateurs pourraient utiliser ces informations d'une manière ou d'une autre pour l'optimisation, et les analyseurs statiques peuvent utiliser ces informations pour s'assurer que la fonction ne reçoit jamais de pointeur nul (ou, si elle peut le dire, un tableau avec moins d'éléments que spécifié).static
dans C99. Il a plus de dix ans et demi, mais tous les auteurs de compilateurs n'ont pas embrassé toutes les fonctionnalités de C99 - donc C99 dans son ensemble reste largement inconnu.int arr[n];
, alors c'est un VLA (tableau de longueur variable) , qui a été ajouté en C99. C'est ce que vous vouliez dire?Réponse courte ... cela dépend.
Les variables locales définies statiquement ne perdent pas leur valeur entre les appels de fonction. En d'autres termes, ce sont des variables globales, mais limitées à la fonction locale dans laquelle elles sont définies.
Les variables globales statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.
Les fonctions statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.
la source
private
en ait pas en C, votre analogie est bonne: statique rend les choses "privées" à un fichier donné. Et les fichiers en C sont souvent mappés aux classes en C ++.Exemple de portée variable multi-fichiers
Ici, j'illustre comment statique affecte la portée des définitions de fonction sur plusieurs fichiers.
ac
principal c
GitHub en amont .
Compiler et exécuter:
Production:
Interprétation
si
, une pour chaque fichieri
Comme d'habitude, plus la portée est petite, mieux c'est, donc toujours déclarer des variables
static
si vous le pouvez.En programmation C, les fichiers sont souvent utilisés pour représenter des "classes", et
static
variables représentent des membres statiques privés de la classe.Ce que les normes en disent
C99 N1256 draft 6.7.1 "Storage-class specifiers" dit que
static
s'agit d'un "stockage-class specifier".6.2.2 / 3 "Liens d'identifiants" dit
static
impliqueinternal linkage
:et 6.2.2 / 2 dit que
internal linkage
se comporte comme dans notre exemple:où "unité de traduction est un fichier source après le prétraitement.
Comment GCC l'implémente-t-il pour ELF (Linux)?
Avec le
STB_LOCAL
reliure.Si nous compilons:
et démontez la table des symboles avec:
la sortie contient:
donc la liaison est la seule différence significative entre eux.
Value
est juste leur décalage dans le.bss
section, nous nous attendons donc à ce qu'il diffère.STB_LOCAL
est documenté sur la spécification ELF à http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :ce qui en fait un choix parfait pour représenter
static
.Les variables sans statique sont
STB_GLOBAL
, et la spécification dit:ce qui est cohérent avec les erreurs de liaison sur plusieurs définitions non statiques.
Si nous augmentons l'optimisation avec
-O3
, lesi
symbole est entièrement supprimé de la table des symboles: il ne peut en aucun cas être utilisé de l'extérieur. TODO pourquoi garder les variables statiques sur la table des symboles quand il n'y a pas d'optimisation? Peuvent-ils être utilisés pour quelque chose? Peut-être pour le débogage.Voir également
static
fonctions: https://stackoverflow.com/a/30319812/895245static
avecextern
, ce qui fait "le contraire": Comment utiliser extern pour partager des variables entre des fichiers source?Espaces de noms anonymes C ++
En C ++, vous souhaiterez peut-être utiliser des espaces de noms anonymes au lieu de statiques, ce qui produit un effet similaire, mais masque en outre les définitions de type: espaces de noms sans nom / anonymes vs fonctions statiques
la source
Ça dépend:
La fonction retournerait 1, 2, 3, etc. --- la variable n'est pas sur la pile.
ac:
Cela signifie que cette fonction n'a de portée que dans ce fichier. Donc, ac et bc peuvent avoir des
foo()
s différents , et foo n'est pas exposé aux objets partagés. Donc, si vous avez défini foo en ac, vous ne pouvez pas y accéder depuisb.c
ou depuis d'autres endroits.Dans la plupart des bibliothèques C, toutes les fonctions "privées" sont statiques et la plupart "publiques" ne le sont pas.
la source
Les gens continuent à dire que «statique» en C a deux significations. Je propose une autre façon de le voir qui lui donne un sens unique:
La raison pour laquelle il semble avoir deux significations est que, en C, chaque élément auquel «statique» peut être appliqué possède déjà l'une de ces deux propriétés , il semble donc que cet usage particulier n'implique que l'autre.
Par exemple, considérez les variables. Les variables déclarées en dehors des fonctions ont déjà une persistance (dans le segment de données), donc appliquer 'statique' ne peut que les rendre non visibles en dehors de la portée actuelle (unité de compilation). Au contraire, les variables déclarées à l'intérieur des fonctions ont déjà une non-visibilité en dehors de la portée (fonction) actuelle, donc l'application de «statique» ne peut que les rendre persistantes.
Appliquer «statique» aux fonctions revient à l'appliquer aux variables globales - le code est nécessairement persistant (au moins dans le langage), donc seule la visibilité peut être modifiée.
REMARQUE: ces commentaires s'appliquent uniquement à C. En C ++, appliquer «statique» aux méthodes de classe donne vraiment au mot-clé une signification différente. De même pour l'extension d'argument tableau C99.
la source
static
donne un lien interne à un identifiant.De Wikipédia:
la source
static
signifie des choses différentes dans des contextes différents.Vous pouvez déclarer une variable statique dans une fonction C. Cette variable n'est visible que dans la fonction mais elle se comporte comme une globale dans la mesure où elle n'est initialisée qu'une seule fois et conserve sa valeur. Dans cet exemple, chaque fois que vous appelez
foo()
, un nombre croissant sera imprimé. La variable statique n'est initialisée qu'une seule fois.Une autre utilisation de statique est lorsque vous implémentez une fonction ou une variable globale dans un fichier .c mais que vous ne voulez pas que son symbole soit visible en dehors de celui
.obj
généré par le fichier. par exemplela source
Si vous déclarez une variable dans une fonction statique, sa valeur ne sera pas stockée dans la pile d'appels de fonction et sera toujours disponible lorsque vous appellerez à nouveau la fonction.
Si vous déclarez une variable globale statique, sa portée sera limitée au sein du fichier dans lequel vous l'avez déclarée. Ceci est légèrement plus sûr qu'un global régulier qui peut être lu et modifié tout au long de votre programme.
la source
Je déteste répondre à une vieille question, mais je ne pense pas que quiconque ait mentionné comment K&R l'explique dans la section A4.1 du "Langage de programmation C".
En bref, le mot statique est utilisé avec deux significations:
static
mot - clé (grand accent mis sur son utilisation dans le code en tant que mot-clé) est utilisé avec une déclaration, il donne à cet objet un lien interne de sorte qu'il ne peut être utilisé que dans cette unité de traduction. Mais si le mot-clé est utilisé dans une fonction, il change la classe de stockage de l'objet (l'objet ne serait de toute façon visible que dans cette fonction). L'opposé de statique est leextern
mot - clé, qui donne un lien externe à un objet.Peter Van Der Linden donne ces deux significations dans "Expert C Programming":
la source
register
un spécificateur de classe de stockage (C99 6.7.1 Spécificateurs de classe de stockage). Et c'est plus qu'un simple indice, par exemple, vous ne pouvez pas appliquer l'opérateur address-of&
sur un objet avec une classe de stockage,register
que le compilateur alloue ou non un registre.En C, statique a deux significations, selon l'étendue de son utilisation. Dans la portée globale, lorsqu'un objet est déclaré au niveau du fichier, cela signifie que cet objet n'est visible que dans ce fichier.
À toute autre portée, il déclare un objet qui conservera sa valeur entre les différents moments où la portée particulière est entrée. Par exemple, si un int est supprimé dans une procédure:
la valeur de «i» est initialisée à zéro lors du premier appel à la procédure et la valeur est conservée à chaque appel ultérieur de la procédure. si «i» était imprimé, il produirait une séquence de 0, 1, 2, 3, ...
la source
Il est important de noter que les variables statiques dans les fonctions sont initialisées à la première entrée dans cette fonction et persistent même après la fin de leur appel; en cas de fonctions récursives, la variable statique n'est initialisée qu'une seule fois et persiste également pendant tous les appels récursifs et même après la fin de l'appel de la fonction.
Si la variable a été créée en dehors d'une fonction, cela signifie que le programmeur ne peut utiliser la variable que dans le fichier source, la variable a été déclarée.
la source
Si vous le déclarez dans un
mytest.c
fichier:Cette variable n'est alors visible que depuis ce fichier. La variable ne peut pas être exportée ailleurs.
Si vous déclarez à l'intérieur d'une fonction, la valeur de la variable gardera sa valeur à chaque appel de la fonction.
Une fonction statique ne peut pas être exportée de l'extérieur du fichier. Donc dans un
*.c
fichier, vous cachez les fonctions et les variables si vous les déclarez statiques.la source
Les variables statiques en C ont la durée de vie du programme.
S'ils sont définis dans une fonction, ils ont une portée locale, c'est-à-dire qu'ils ne sont accessibles qu'à l'intérieur de ces fonctions. La valeur des variables statiques est préservée entre les appels de fonction.
Par exemple:
Dans le programme ci-dessus,
var
est stocké dans le segment de données. Sa durée de vie est l'ensemble du programme C.Après l'appel de fonction 1,
var
devient 2. Après l'appel de fonction 2,var
devient 3.La valeur de
var
n'est pas détruite entre les appels de fonctions.S'il y
var
avait entre une variable non statique et locale, il serait stocké dans le segment de pile dans le programme C. Étant donné que le cadre de pile de la fonction est détruit après le retour de la fonction, la valeur devar
est également détruite.Les variables statiques initialisées sont stockées dans le segment de données du programme C tandis que celles non initialisées sont stockées dans le segment BSS.
Une autre information sur statique: si une variable est globale et statique, elle a la durée de vie du programme C, mais elle a une portée de fichier. Il n'est visible que dans ce fichier.
Pour essayer ceci:
file1.c
file2.c
Essayez maintenant de les lier en utilisant:
Cela donnerait une erreur de l'éditeur de liens car x a la portée de fichier de file1.c et l'éditeur de liens ne pourrait pas résoudre la référence à la variable x utilisée dans file2.c.
Références:
la source
static int var = 1;
changez-vous pas la valeur à un à chaque foisUne variable statique est une variable spéciale que vous pouvez utiliser dans une fonction. Elle enregistre les données entre les appels et ne les supprime pas entre les appels. Par exemple:
Le résultat:
la source
printf("%d, ", count); count++;
par `printf ("% d, ", count ++) (pas important: P).Une valeur de variable statique persiste entre différents appels de fonction et sa portée est limitée au bloc local une variable statique initialise toujours avec la valeur 0
la source
Il y a 2 cas:
(1) Variables locales déclarées
static
: allouées dans le segment de données au lieu de la pile. Sa valeur est conservée lorsque vous appelez à nouveau la fonction.(2) Variables ou fonctions globales déclarées
static
: unité de compilation extérieure invisible (c'est-à-dire sont des symboles locaux dans la table des symboles lors de la liaison).la source
Les variables statiques ont la propriété de conserver leur valeur même lorsqu'elles sont hors de leur portée! Par conséquent, les variables statiques conservent leur valeur précédente dans leur étendue précédente et ne sont pas initialisées à nouveau dans la nouvelle étendue.
Regardez ceci par exemple - Une variable int statique reste en mémoire pendant l'exécution du programme. Une variable normale ou automatique est détruite lorsqu'un appel de fonction où la variable a été déclarée est terminé.
Cela produira: 1 2
Comme 1 reste dans la mémoire car il a été déclaré statique
Les variables statiques (comme les variables globales) sont initialisées à 0 si elles ne sont pas initialisées explicitement. Par exemple, dans le programme ci-dessous, la valeur de x est imprimée comme 0, tandis que la valeur de y est quelque chose d'ordure. Voir ceci pour plus de détails.
Cela produira: 0 [some_garbage_value]
Ce sont les principaux que j'ai trouvés qui n'ont pas été expliqués ci-dessus pour un débutant!
la source
Dans la programmation C,
static
est un mot-clé réservé qui contrôle à la fois la durée de vie et la visibilité. Si nous déclarons une variable statique dans une fonction, elle ne sera visible que dans cette fonction. Dans cette utilisation, la durée de vie de cette variable statique commencera lors d'un appel de fonction et sera détruite après l'exécution de cette fonction. vous pouvez voir l'exemple suivant:Le programme ci-dessus nous donnera ce résultat:
Parce que dès que nous appelons la fonction, elle initialise le
count = 0
. Et pendant que nous l'exécutons,counterFunction
il détruira la variable de comptage.la source