As chamadas aninhadas podem levar a argumentos não inicializados em C?
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?
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.