Question

Je reçois cette erreur

error: Access.Core may be used uninitialized in this function

Et voici mon code:

 static int FirstTime = 1;
 MyStruct Access;

 if (FirstTime) {
   FirstTime = 0;
   Access = Implementation();
   DoSomething(Access);
 }

 if(Other_Variable) {
    Access = Implementation2();
    DoSomething(Access);
  }

  //The Other_Variable will be set to 1 and to 0 by other part of the code

Mon code est comme ça parce que je veux appeler la fonction Implémentation seulement la première fois. À chaque appel, la variable Access va être mise à jour, il n’est donc pas logique de la rendre statique.

Si je fais en sorte qu'Access soit statique, mais que je n'aime pas le faire, car dans chaque autre appel, Access sera mis à jour. Comment éviter le problème sans le rendre statique?

De même, toute meilleure option permettant d'exécuter une seule fois une fonction au lieu d'utiliser une variable statique est la bienvenue.

Était-ce utile?

La solution

Créez Access comme ceci (et supprimez FirstTime et le si ):

static MyStruct Access = Implementation(this_b);

Vous recevez cet avertissement parce que les variables statiques survivent à un appel de fonction. Leur valeur est conservée pour tous les appels de fonction ( sans que définisse le thread qui appelle cette fonction). Ainsi, FirstTime contrôlera si vous initialisez Access . La première fois que vous appelez la fonction dans laquelle se trouve le code, la variable Access sera correctement initialisée. Mais à chaque nouvel appel de fonction, FirstTime vaut zéro et ne pas initialisez Access , et utilisera donc une variable non initialisée dans le code. .

Modifier: Maintenant, avec vos informations mises à jour, vous indiquez que vous disposez de deux fonctions Mise en œuvre . La première fois que vous souhaitez en utiliser une et toutes les autres fois, vous souhaitez utiliser une autre fonction. Que diriez-vous de cela alors:

 // static will be false/zero by default
 static bool AlreadyCalled;
 MyStruct Access;

 if (!AlreadyCalled) {
   Access = Implementation();
   AlreadyCalled = true;
 } else {
   Access = Implementation2();
 }

Toutefois, selon votre cas d'utilisation réel, il existe peut-être de meilleures façons de gérer cela. Par exemple, pourquoi ne pas mettre à jour l'état de Access , comme suit:

// let the default constructor initialize it
// to a plausible state
static MyStruct Access;

// use RAII to update the state of Access when this
// function returns. 
MyUpdater updater(Access);

// now, do whatever the function does. 

Quelque chose comme ça pour MyUpdater :

struct MyUpdater {
    MyStruct &s;
    MyUpdater(MyStruct &s):s(s) { }
    ~MyUpdater() {
        s.ChangeState();
    }
};

Ce modèle s'appelle RAII : vous associez une action utile au constructeur et au destructeur d'un objet alloué localement.

Autres conseils

La réponse de @ litb est intéressante. Un programme équivalent suit. Le code est compilé et fonctionne comme indiqué en C ++, mais pas en C.

#include <stdio.h>

static int newval(void) { return 3; }

void inc(void)
{
    static int a = newval();

    a++;
    printf("%d\n", a);
}

int main(void)
{
    int i;
    for (i = 0; i < 10; i++)
        inc();
    return(0);
}

gcc dit:

x.c: dans la fonction 'inc': x.c: 7: erreur: l'élément d'initialisation n'est pas constant

g ++ en est assez satisfait.

C’est une différence entre C et C ++ dont je n’étais pas au courant (mais cela ne correspond pas à 300 caractères, je ne peux donc pas en faire un commentaire, facilement).

@Eduardo a posé l'une des questions suivantes dans les commentaires: "Pourquoi C n'autorise-t-il pas cela et C ++ ne l'autorise-t-il pas?". Étant donné que la réponse contient plus de 300 caractères ...

Comme @litb l'a dit dans les commentaires, en C, vous ne pouvez utiliser des constantes que pour les initialiseurs de variables statiques. Cela s'explique en partie par le fait que les valeurs sont définies avant l'appel de main () et qu'aucune fonction définie par l'utilisateur n'est appelée avant l'appel de main (). C ++, en revanche, autorise l'initialisation des variables globales et statiques par les constructeurs (définis par l'utilisateur) avant l'appel de main (). Il n'y a donc aucune raison de ne pas autoriser l'appel d'autres fonctions définies par l'utilisateur. L'initialisation est donc raisonnable. Avec C89, vous êtes limité dans les initialiseurs que vous pouvez utiliser avec des variables automatiques (locales); en C99, vous pouvez utiliser à peu près n'importe quelle expression pour initialiser une variable locale.

L'accès n'est pas statique, donc une nouvelle instance est créée chaque fois que la fonction est appelée. Ce n'est que la première fois que vous lui attribuez une valeur quelconque; cette valeur est perdue dès que la fonction est fermée.

Si vous avez besoin qu'Access persiste dans tous les appels à la fonction, rendez-la statique.

Access n'est pas statique et doit donc être créé à chaque appel.

Envisagez de simplifier le code pour obtenir quelque chose comme:

static MyStruct Access = Implementation(this_b);

Cela garantit que la fonction ne sera appelée que lors de la première exécution de la méthode et que Access conservera la valeur entre les appels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top