As chamadas aninhadas podem levar a argumentos não inicializados em C?

StackOverflow https://stackoverflow.com/questions/2121327

  •  22-09-2019
  •  | 
  •  

Pergunta

É len corretamente inicializado e seguro em set_array ligar?

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), len);
}

Caso contrário, o que você recomendaria?

Foi útil?

Solução

Não - não há ordem de avaliação definida para argumentos para uma chamada de função.

Mesmo que a chamada para object_get_array() tem que ocorrer antes da chamada para object_set_array(), o valor que o compilador calcula e passa para object_set_array() para o len O parâmetro pode ser feito antes que o compilador faça a chamada para object_get_array().

Não tenho certeza do que o segundo parâmetro para o object_set_array() A chamada deve ser - talvez você quisesse usar o operador de vírgula:

void object_foo (Object* self, Object* obj) {
    int len;

    object_set_array (self, (object_get_array (obj, &len), len));
}

O que funcionaria, mas é confuso e algo que eu não recomendaria.

Eu acho que o que você quer é:

void object_foo (Object* self, Object* obj) {
    int len;

    object_get_array (obj, &len);  // get the length from obj

    object_set_array (self, len)); // set the len for self
}

Outras dicas

Não. O terceiro parâmetro de object_set_array() pode ser avaliado e empurrado para a pilha antes do segundo parâmetro (object_get_array()) é avaliado.

Provavelmente você quer

void object_copy (Object* self, Object* obj) {
    int len;
    /* I'm just guessing as to the return type */
    Object *pObj = object_get_array(obj, &len); 
    object_set_array (self, pObj, len);
}

Você está passando len por valor no object_set_array() Ligue antes de ser inicializado. Então isso está errado e um bom compilador avisará sobre isso. A variável conterá um valor aleatório, para que o código não falhe, mas não fará o que você provavelmente deseja.

Se object_get_array falha, então len pode não ser inicializado. Seria melhor ligar object_get_array primeiro antes de ligar object_set_array, dessa forma, você pode testar se a chamada funcionou ou não.

Aqui está um código de exemplo, observe que eu não sei o que object_get_array retorna então eu usei um void * Para facilitar a explicação:

void *obj;
obj = object_get_array(obj, &len);
if (obj != NULL) object_set_array(self, obj, len);

O código que você escreveu é perigoso, mas recorrer a atalhos como esse pode levar você a pensar que object_set_array falhou e não object_get_array. Você precisa julgar por si mesmo, se isso falhar ou não, sempre presumo que o código falhe para que eu possa colocar salvaguardas, sua abordagem será diferente, certos atalhos estão bem, este não é!

Mesmo assim, o código C é executado da esquerda para a direita, na ordem de como a expressão é avaliada (depende do compilador e do código compilado), se a função funcionou, então sim, len seria inicializado, mas não é seguro.

Espero que isso ajude, cumprimentos, Tom.

Isso também funcionará:

ARRAY object_get_array (Object* self, int* len);
void object_set_array (Object* self, ARRAY array, const int* len);

// ...

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), &len);
}

Porque a chamada para object_get_array() sempre será avaliado antes da chamada para object_set_array(), em que ponto len terá sido definido com o valor correto.

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