J'ai vu le mot static
utilisé à différents endroits dans le code C ; est-ce comme une fonction/classe statique en C# (où la mise en œuvre est partagée entre plusieurs objets) ?
Réponses
Trop de publicités?- Une variable statique à l'intérieur d'une fonction conserve sa valeur entre les invocations.
- Une variable globale statique ou une fonction n'est "vue" que dans le fichier dans lequel elle est déclarée.
(1) est le sujet le plus étranger si vous êtes un débutant, voici donc un exemple :
#include <stdio.h>
void foo()
{
int a = 10;
static int 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();
}
Cette empreinte :
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
Ceci est utile dans les cas où une fonction doit conserver un certain état entre les invocations, et où vous ne voulez 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 une fonctionnalité de "contrôle d'accès". Si vous avez un fichier .c qui implémente une certaine fonctionnalité, il n'expose généralement que quelques fonctions "publiques" aux utilisateurs. Le reste de ses fonctions doit être rendu static
afin que l'utilisateur ne puisse pas y accéder. C'est l'encapsulation, une bonne pratique.
Citation : Wikipedia :
Dans le langage de programmation C, le terme statique est utilisé avec les variables globales et les fonctions fonctions pour définir leur portée au fichier fichier qui les contient. Dans les variables locales, static est utilisé pour stocker la variable dans la mémoire allouée statiquement au lieu de la mémoire allouée automatiquement automatiquement. Bien que le langage ne ne dicte pas l'implémentation 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 du programme au moment de la compilation temps, tandis que la mémoire automatiquement mémoire allouée automatiquement est normalement implémentée comme une pile d'appels transitoire.
Voir ici et ici pour plus de détails.
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 les attributs de classe (partagés entre tous les objets de la même classe) et les méthodes. En C, il n'y a pas de classes, cette fonctionnalité n'est donc pas pertinente.
Il y a une autre utilisation qui n'est pas couverte ici, et c'est dans le cadre d'une déclaration de type tableau comme argument d'une fonction :
int someFunction(char arg[static 10])
{
...
}
Dans ce contexte, cela spécifie que les arguments passés à cette fonction doivent être un tableau de type char
avec au moins 10 éléments. Pour plus d'informations, voir ma question ici .
Réponse courte ... ça 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 dont la portée est limitée à 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.
Un exemple pour clarifier l'utilisation de l'étendue multi-fichier pour les fonctions et les variables, y compris la différence avec extern
(J'avais l'habitude de mélanger les deux) :
\== a.h \=======================================
// ERROR:
// Multiple definitions because
// included in multiple files.
//int aHInt = 0;
// OK
// Unlike variables, functions have
// extern semantics by default.
void a();
static int aHStaticInt = 0;
extern int externInt;
\== a.c \=======================================
#include <stdio.h>
#include "a.h"
// ERROR:
// Multiple definitions because
// already defined in main.
//int i = 0;
// OK because static, even if also defined in main.c.
static int staticInt = 0;
// This is where it is initialised.
int externInt = 0;
// ERROR:
// Already defined in main
//void func(){}
// OK because static, even if also defined in main.c.
static void staticFunc() {
printf( "a#staticFunc:\n" );
printf( " staticInt = %d\n", staticInt );
printf( " aHStaticInt = %d\n", aHStaticInt );
printf( " externInt = %d\n", externInt );
puts("");
}
void a() {
staticFunc();
staticInt++;
aHStaticInt++;
externInt++;
}
\== main.c \=======================================
#include <stdio.h>
#include "a.h"
int mainInt = 0;
static int staticInt = 0;
// WARNING in gcc 4.8 -Wall.
// We have already initialised this `extern` in `a.c`.
//extern int externIntInit = 0;
static void staticFunc() {
printf( "main#staticFunc:\n" );
printf( " staticInt = %d\n", staticInt );
printf( " aHStaticInt = %d\n", aHStaticInt );
printf( " externInt = %d\n", externInt );
puts("");
}
int main(int argc, char** argv) {
staticFunc();
a();
staticFunc();
a();
}
\== Sortie \=======================================
main#staticFunc:
staticInt = 0
aHStaticInt = 0
externInt = 0
a#staticFunc:
staticInt = 0
aHStaticInt = 0
externInt = 0
main#staticFunc:
staticInt = 0
aHStaticInt = 0
externInt = 1
a#staticFunc:
staticInt = 1
aHStaticInt = 1
externInt = 1
a#staticFunc:
staticInt = 2
aHStaticInt = 2
externInt = 2
Interprétation
Il y a deux des variables distinctes pour les deux mainStaticInt
et aHStaticInt
et deux fonctions distinctes pour staticFunc
. L'un d'eux n'est visible que dans main.c
et l'autre uniquement visible dans a.c
.
Il existe un simple variable externInt
visible des deux côtés main.c
et a.c
. Il existe également une fonction unique a()
car les fonctions ont extern
par défaut.
Rappelez-vous que #include
fait un simple copier-coller de fichiers. Par conséquent, pour l'inclusion d'une variable statique ou d'une définition de fonction dans un en-tête, vous obtenez une nouvelle version locale.
Utilisation
Si une variable/fonction globale est destinée à être utilisée sur une simple et le déclarer statique pour éviter qu'il ne soit redéfini ailleurs. Vous ne les définirez généralement pas dans l'en-tête, puisque les en-têtes existent principalement pour partager les déclarations.
Si une variable globale est destinée à être utilisée à travers multiple l'initialiser une fois et le déclarer en tant que externe sur les fichiers où vous voulez l'utiliser, éventuellement sur un seul en-tête. A utiliser avec précaution, ou vous risquez d'oublier qu'il s'agit de la même variable sur plusieurs fichiers.
Essayez-le vous-même
J'ai cet exemple sur mon github donc si quelqu'un veut jouer avec, clone, va dans c/multifile/
, make, exécutez les fichiers de sortie et jetez un coup d'œil à main.c
, a.c
et a.h
.
Ça dépend :
int foo()
{
static int x;
return ++x;
}
Cela renverrait 1,2,3 et ainsi de suite --- la variable n'est pas sur la pile.
a.c:
static int foo()
{
}
Cela signifie que cette fonction n'a de portée que dans ce fichier. Ainsi, si a.c et b.c peuvent avoir des valeurs différentes, cela signifie que la fonction n'a pas de portée. foo()
et foo n'est pas exposé aux objets partagés. Donc si vous avez défini foo dans a.c vous ne pouvez pas y accéder depuis b.c
ou de tout autre endroit.
Dans la plupart des bibliothèques C, toutes les fonctions "privées" sont statiques et la plupart des fonctions "publiques" ne le sont pas.
- Réponses précédentes
- Plus de réponses