Qu'est ce qu'un "statique" de la fonction?

la question portait sur les méthodes simples c fonctions, pas c++ static , comme clarifié dans les commentaires.

Ok, je comprends ce qu'est une variable static , mais qu'est-ce qu'une fonction static ?

et pourquoi est - ce que si je déclare une fonction, disons void print_matrix , dans disons a.c (sans a.h ) et incluons "a.c" - j'obtiens "print_matrix@@....) already defined in a.obj" , mais si je le déclarer comme static void print_matrix puis il compile?

mise à jour juste pour clarifier les choses - je sais qu'inclure .c est mauvais, comme beaucoup d'entre vous l'ont souligné. Je le fais juste pour libérer Temporairement l'espace dans main.c jusqu'à ce que j'ai une meilleure idée de la façon de grouper toutes ces fonctions dans les fichiers .h et .c . Juste une solution temporaire et rapide.

414
demandé sur Alex 2009-02-17 21:26:02

11 réponses

static les fonctions sont des fonctions qui ne sont visibles que pour d'autres fonctions dans le même fichier (plus précisément le même Unité de traduction ).

EDIT : pour ceux qui pensaient que l'auteur des questions signifiait une" méthode de classe": comme la question est étiquetée C il signifie une fonction C simple et ancienne. For (C++/Java/...) classe méthodes, static signifie que cette méthode peut être appelé de la classe elle-même, aucune instance de cette classe est nécessaire.

580
répondu Johannes Weiss 2015-04-28 20:29:22

il y a une grande différence entre les fonctions statiques en C et les fonctions statiques des membres en C++. En C, une fonction statique n'est pas visible en dehors de son unité de traduction, qui est le fichier objet dans lequel elle est compilée. En d'autres termes, rendre une fonction statique limite sa portée. Vous pouvez penser à une fonction statique comme étant "privé" de sa *.c fichier (même si cela n'est pas strictement exact).

en C++, "static" peut aussi s'appliquer aux fonctions des membres et aux données des membres de classe. Une donnée membre statique est aussi appelée "variable de classe", alors qu'un non-membre de données statiques est une "variable d'instance". C'est de la terminologie Smalltalk. Cela signifie qu'il n'existe qu'une seule copie d'une donnée membre statique partagée par tous les objets d'une classe, alors que chaque objet possède sa propre copie d'un non-membre de données statiques. Donc une donnée membre statique est essentiellement une variable globale, qui est un membre d'une classe.

Non-fonctions membres statiques peuvent accéder à toutes les données membres de la classe: statique et non statique. Les fonctions de membre statique ne peuvent fonctionner que sur les membres de données statiques.

Une façon de penser, c'est qu'en C++ statique membres de données et fonctions membres statiques n'appartiennent pas à n'importe quel objet, mais à l'ensemble de la classe.

177
répondu Dima 2017-04-04 11:13:40

il y a deux utilisations pour le mot-clé statique quand il s'agit de fonctions en C++.

la première est de marquer la fonction comme ayant un lien interne de sorte qu'elle ne peut pas être référencée dans d'autres unités de traduction. Cet usage est déprécié en C++. Les espaces de noms sans nom sont préférés pour cet usage.

// inside some .cpp file:

static void foo();    // old "C" way of having internal linkage

// C++ way:
namespace
{
   void this_function_has_internal_linkage()
   {
      // ...
   }
}

La deuxième utilisation est dans le contexte d'une classe. Si une classe a une fonction membre statique, ce qui signifie que la fonction membre de la classe (et a l'accès habituel aux autres membres), mais il n'a pas besoin d'être invoqué à travers un objet particulier. En d'autres termes, à l'intérieur de cette fonction, il n'y a pas de pointeur "ceci".

69
répondu Brian Neal 2009-02-17 21:08:30

Minimal praticable multi-exemple de fichier

A. c :

#include <stdio.h>

/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
/q/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c-files-while-gcc-does-not-69756/"a f"); }*/

/* OK: only declared, not defined. Will use the one in main. */
void f(void);

/* OK: only visible to this file. */
static void sf() { puts("a sf"); }

void a() {
    f();
    sf();
}

principal.c :

#include <stdio.h>

void a(void);        

void f() { puts("main f"); }

static void sf() { puts("main sf"); }

void m() {
    f();
    sf();
}

int main() {
    m();
    a();
    return 0;
}

Compilation :

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o

Sortie :

main f
main sf
main f
a sf

interprétation

  • il y a deux fonctions distinctes sf , une pour chaque fichier
  • il y a une seule fonction partagée f

comme d'habitude, le plus petit la portée, le mieux, donc toujours déclarer des fonctions static si vous pouvez.

dans la programmation C, les fichiers sont souvent utilisés pour représenter les" classes", et les fonctions static représentent les méthodes" privées " de la classe.

un motif C courant est de passer un this structuré autour du premier argument" method", qui est fondamentalement ce que C++ fait sous le capot.

Quelles sont les normes à dire sur le sujet

C99 N1256 projet 6.7.1 "de Stockage de classe prescripteurs", dit que static est une "catégorie de stockage spécificateur".

6.2.2/3 "Liens de identificateurs" dit static implique internal linkage :

si la déclaration d'un identifiant de portée de fichier pour un objet ou une fonction contient le spécificateur de classe de stockage statique, l'identifiant a un lien interne.

et 6.2.2 / 2 dit que internal linkage se comporte comme dans notre exemple:

Dans l'ensemble des unités de traduction et des bibliothèques qui constitue tout un programme, chaque déclaration d'un identifiant particulier avec liaison externe indique le même objet ou la même fonction. Au sein d'une unité de traduction, chaque déclaration d'un identificateur avec lien interne indique le même objet ou la même fonction.

où "l'unité de traduction" est un fichier source après prétraitement.

comment GCC le met en œuvre pour ELF (Linux)?

avec la liaison STB_LOCAL .

si nous compilons:

int f() { return 0; }
static int sf() { return 0; }

et démonter la table de symboles avec:

readelf -s main.o

la sortie contient:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 000000000000000b    11 FUNC    LOCAL  DEFAULT    1 sf
  9: 0000000000000000    11 FUNC    GLOBAL DEFAULT    1 f

si la liaison est la seule différence significative entre eux. Value est juste leur offset dans la section .bss , donc nous nous attendons à ce qu'il diffère.

STB_LOCAL est documenté sur l'ELFE spec http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

STB_LOCAL les symboles locaux ne sont pas visibles à l'extérieur du fichier objet contenant leur définition. Les 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 .

fonctions sans statique sont STB_GLOBAL , et le spec dit:

lorsque l'éditeur de liens combine plusieurs fichiers objet déplaçables, il ne permet pas de définir plusieurs symboles STB_GLOBAL avec le même nom.

qui est cohérent avec les erreurs de lien sur plusieurs définitions non statiques.

si nous activons l'optimisation avec -O3 , le symbole sf est entièrement enlevé de la table de symboles: il ne peut pas être utilisé de en dehors de toute façon. Pourquoi garder les fonctions statiques sur la table de symboles quand il n'y a pas d'optimisation? Peut-on les utiliser pour quelque chose?

Voir aussi

Essayez-le vous-même

exemple sur GitHub pour vous de jouer avec.

34

ce qui suit concerne les fonctions C simples - dans une Classe C++, le modificateur 'static' a une autre signification.

si vous n'avez qu'un fichier, ce modificateur ne fait absolument aucune différence. La différence vient dans les plus grands projets avec plusieurs fichiers:

en C, chaque "module" (une combinaison d'échantillon.c et l'échantillon.h) est compilé indépendamment et ensuite chacun de ces fichiers objets compilés (échantillon.o) sont liées à un fichier exécutable par l'éditeur de liens.

disons que vous avez plusieurs fichiers que vous incluez dans votre fichier principal et deux d'entre eux ont une fonction qui est seulement utilisée en interne pour la commodité appelée add(int a, b) - le compilateur créerait facilement des fichiers objet pour ces deux modules, mais le linker lancera une erreur, parce qu'il trouve deux fonctions avec le même nom et il ne sait pas lequel il devrait utiliser (même s'il n'y a rien à relier, parce qu'ils ne sont pas utilisés ailleurs, mais dans son propre fichier.)

c'est pourquoi vous faites de cette fonction, qui n'est utilisée qu'interne, une fonction statique. Dans ce cas, le compilateur ne crée pas le type "vous pouvez lier cette chose"-drapeau pour le linker, de sorte que le linker ne voit pas cette fonction et ne générera pas d'erreur.

18
répondu dersimn 2013-04-25 22:49:07

tout d'abord: c'est généralement une mauvaise idée d'inclure un fichier .cpp dans un autre fichier - cela conduit à des problèmes comme celui-ci: -) la manière normale est de créer des unités de compilation séparées, et Ajouter un fichier d'en-tête pour le fichier inclus.

second:

C++ a quelque terminologie confuse ici - Je ne le savais pas jusqu'à ce que souligné dans les commentaires.

a) static functions - hérité de C, et ce que vous parlez ici. En dehors de toute classe. Une fonction statique signifie qu'elle n'est pas visible en dehors de l'Unité de compilation actuelle - donc dans votre cas A. obj a une copie et votre autre code a une copie indépendante. (Gonflage de l'exécutable final avec plusieurs copies du code).

b) static member function - qu'est-ce que L'Orientation de L'objet des termes une statique méthode . Vit à l'intérieur d'une classe. Vous appelez cela avec la classe, plutôt que par un l'instance de l'objet.

ces deux définitions de fonctions statiques différentes sont complètement différentes. Attention, ici il y a des dragons.

14
répondu Douglas Leeder 2014-06-24 06:06:46

les définitions des fonctions statiques indiquent que ce symbole est interne. Ainsi, il ne sera pas visible pour lier de l'extérieur, mais seulement aux fonctions dans la même unité de compilation, généralement le même fichier.

13
répondu raimue 2009-02-17 18:28:44

Une fonction statique est celui qui peut être appelé la classe elle-même, par opposition à une instance de la classe.

par exemple un non-statique serait:

Person* tom = new Person();
tom->setName("Tom");

cette méthode fonctionne sur une instance de la classe, pas sur la classe elle-même. Cependant, vous pouvez avoir une méthode statique qui peut fonctionner sans disposer d'une instance. Cela est parfois utilisé dans le modèle de L'usine:

Person* tom = Person::createNewPerson();
8
répondu Parrots 2009-02-17 18:31:56

Mineur nit: fonctions statiques sont visibles à une unité de traduction, qui dans la plupart des cas est le fichier de la fonction est définie. L'erreur que vous obtenez est communément appelée violation de la règle de la définition unique.

la norme dit probablement quelque chose comme:

"Chaque programme doit contenir exactement une définition de chaque noninline fonction ou objet qui est utilisé dans ce programme; aucun diagnostic requis."

C'est la façon de voir les fonctions statiques. Ceci est toutefois déprécié en C++.

en C++, en plus, vous pouvez déclarer les fonctions de membre statiques. Il s'agit le plus souvent de méta-fonctions, c'est-à-dire qu'elles ne décrivent pas/ne modifient pas le comportement/l'état d'un objet particulier, mais agissent sur l'ensemble de la classe elle-même. Aussi, cela signifie que vous n'avez pas besoin de créer un objet pour appeler une fonction membre statique. En outre, cela signifie également que vous obtenez seulement accès aux variables membres statiques à l'intérieur d'une telle fonction.

j'ajouterais à L'exemple de Parrot le modèle Singleton qui est basé sur cette sorte de fonction de membre statique pour obtenir/utiliser un seul objet tout au long de la vie d'un programme.

6
répondu dirkgently 2009-02-17 18:50:57

la réponse à La fonction statique dépend de la langue:

1) dans les langues sans OOPS comme C, cela signifie que la fonction n'est accessible que dans le fichier où elle est définie.

2) dans les langages avec OOPS comme C++ , cela signifie que la fonction peut être appelée directement sur la classe sans en créer une instance.

6
répondu user2410022 2016-03-06 13:31:35

pour la fonction statique dans " C " compiller ne créera pas ses variables internes sur la pile, de sorte que l'appel de fonction statique est plus rapide, et par conséquent, vous ne pouvez pas utiliser des initialiseurs comme: char c='A'.

-4
répondu Alex 2016-11-05 19:17:48