1421 votes

Que signifie "statique" dans un programme C ?

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) ?

1875voto

Eli Bendersky Points 82298
  1. Une variable statique à l'intérieur d'une fonction conserve sa valeur entre les invocations.
  2. 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.

291voto

dreamlax Points 47152

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 .

209voto

Casey Points 19286

Réponse courte ... ça dépend.

  1. 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.

  2. Les variables globales statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.

  3. Les fonctions statiques ne sont pas visibles en dehors du fichier C dans lequel elles sont définies.

87voto

Ciro Santilli Points 3341

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 .

41voto

Artyom Points 17387

Ç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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X