Maison  >  Article  >  développement back-end  >  Pourquoi l'échange de déclarations de variables globales en C entraîne-t-il un comportement inattendu ?

Pourquoi l'échange de déclarations de variables globales en C entraîne-t-il un comportement inattendu ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-30 06:38:03778parcourir

 Why Does Swapping Global Variable Declarations in C   Lead to Unexpected Behavior?

Ordre global d'initialisation en C : ignorer les dépendances

En C , l'ordre d'initialisation des variables globales au sein d'une unité de traduction est bien défini. Cependant, les dépendances entre les variables globales peuvent être ignorées, ce qui entraîne un comportement surprenant.

Considérez le code suivant :

<code class="cpp">struct Foo;

extern Foo globalFoo;

struct Foo {
    Foo() { printf("Foo::Foo()\n"); }
    void add() { printf("Foo::add()\n"); }
    static int addToGlobal() {
        printf("Foo::addToGlobal() START\n");
        globalFoo.add();
        printf("Foo::addToGlobal() END\n");
        return 0;
    }
};

Foo globalFoo;
int dummy = Foo::addToGlobal();

int main() {
    printf("main()\n");
    return 0;
}</code>

Lorsqu'il est compilé avec GCC 4.4.3, le résultat attendu est :

Foo::Foo()
Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
main()

Cela est dû au fait que la variable globale globalFoo est initialisée avant d'appeler la méthode statique Foo::addToGlobal(). Cependant, si nous échangeons l'ordre de globalFoo et de la déclaration factice, le résultat devient :

Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
Foo::Foo()
main()

Il semble que les méthodes d'instance de Foo soient appelées sur une instance non construite. En effet, l'ordre d'initialisation globale ignore les dépendances.

Pour garantir que le constructeur de Foo est appelé avant d'initialiser dummy, nous devons nous assurer que globalFoo est défini avant dummy dans la même unité de traduction. Alternativement, nous pouvons utiliser un pointeur statique vers l'instance globale, qui sera initialisée à null avant toute initialisation dynamique. La méthode addToGlobal peut alors vérifier si le pointeur est nul et créer le Foo global si nécessaire.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn