Pergunta

Estou recebendo este erro

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

E este é meu código:

 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

Meu código é assim porque eu quero chamar para a função Implementação apenas na primeira vez. Em cada chamada a variável de acesso vai ser atualizado para que ele não fazer muitos sentido make-lo estático.

Se eu fizer obras estáticas de acesso, mas eu não gosto de fazer isso estática, porque em todas as outras chamadas de acesso vai ser atualizado. Qualquer forma de evitar o problema sem torná-lo estático?.

Além disso, quaisquer opções melhores para executar apenas uma vez uma função em vez de usar uma variável estática são bem-vindos.

Foi útil?

Solução

Faça Access como este (e FirstTime remove eo if):

static MyStruct Access = Implementation(this_b);

A razão que você receber este aviso é porque variáveis ??estáticas sobreviver uma chamada de função. Seu valor é mantido em todas as chamadas de função ( sem relação aos quais chamadas de rosca que de função). Então, FirstTime irá controlar se você inicializa Access. A primeira vez que você chamar a função que o código é em vão inicializar corretamente a variável Access. Mas com cada novo convite função, FirstTime é zero, e você não initialize Access mais, e, portanto, vai usar uma variável não inicializada para baixo o código.

Editar: Agora, com as informações atualizadas, você diz que você tem duas funções Implementation. A primeira vez que você quiser usar um, e todas as outras vezes que você deseja usar outra função. Como sobre isso, então:

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

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

Dependendo do seu caso de uso real, pode haver melhores maneiras de lidar com isso, porém. Por exemplo, por que não atualizar o estado de Access, como este:

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

Algo como isto para MyUpdater:

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

Esse padrão é chamado RAII: Você associa alguma ação útil com o construtor e destruidor de um objeto alocado localmente.

Outras dicas

resposta

de @ litb é interessante. Um programa equivalente segue. As compilações de código e obras conforme indicado em C ++, mas não compilar em 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 diz:

x.c: Em função 'inc': x.c: 7: Erro: initializer elemento não é constante

g ++ está muito feliz com ele.

Essa é uma diferença entre C e C ++ que eu não estava ciente de (mas isso não iria caber em 300 caracteres, então não posso torná-lo um comentário, facilmente).


@Eduardo perguntou uma das perguntas nos comentários: "Por que C não permite isso e C ++ permite isso?". Como a resposta é mais do que 300 caracteres ...

Como @ litb disse nos comentários, em C você só pode usar constantes para inicializadores de variáveis ??estáticas. Isto é em parte porque os valores são definidos antes principal () é chamado, e não há funções definidas pelo utilizador são chamados antes principal () é chamado. C ++, por outro lado, permite que as variáveis ??globais e estáticos para ser inicializado por construtores (definido pelo usuário) antes de main () é chamado, então não há nenhuma razão para não permitir que outras funções definidas pelo usuário para ser chamado também, para que a inicialização é razoável. Com C89, você está limitado nas initializers você pode usar com variáveis ??automáticas (locais); em C99, você pode usar praticamente qualquer expressão para inicializar qualquer variável local.

O acesso não é estática, toda vez que, portanto, uma nova instância é criada a função é chamada. Só no primeiro tempo através de você realmente atribuir qualquer valor a ela; este valor é perdido assim que a função sai.

Se você precisa de acesso a persistir entre as chamadas para a função, torná-lo estático.

Access não é estática e, portanto, ele deve ser criado em cada chamada.

Considere simplificando o código para algo como:

static MyStruct Access = Implementation(this_b);

Isso garante que a função só serão chamados pela primeira vez o método é executado e que Access vai conter o valor entre chamadas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top