Tentei inicializar uma estrutura por meio de um literal composto em uma função. Depois de resolver uma parte do meu problema (veja Uso de literal composto dentro de uma função para iniciar uma variável em C ), tenho um novo problema com um membro ( ptr_mb
) que deve ser um ponteiro para uma variável.
Este é o código:
typedef struct {
int i_mb;
int * ptr_mb;
} my_struct_t;
void init_struct(my_struct_t **my_struct, int * const ptr) {
*my_struct=&(static my_struct_t) {.i_mb=3, .ptr_mb= ptr};
}
int main() {
int a;
my_struct_t *my_struct;
// my_struct = &(my_struct_t) {.i_mb=3, .ptr_mb=&a}; It is OK
// Try to initialize it in a function
init_struct(&my_struct, &a);
}
Em main()
, funciona (cf linha comentada no programa)
Um erro de compilação foi emitido. Na função init_struct
, ptr não é uma constante (linha *my_struct=&(static my_struct_t) {.i_mb=3, .ptr_mb= ptr};
:).
a
é uma variável declarada em main()
. Assim, seu endereço é constante. Tentei lançar a afetação com (int const *)
, (int * const)
, (int const * const)
, .... Às vezes era bobagem, mas só para tentar e nada funcionou.
É possível fazer tal inicialização em uma função, do jeito que ela funciona main()
?
(Rq. static
é usado. Eu sei que é um padrão C23 e esse padrão ainda não foi publicado; para obter detalhes, consulte esta resposta: Uso de literal composto dentro de uma função para iniciar uma variável em C .)
Não funciona pelo mesmo motivo que isso não funciona:
É preciso perceber que a inicialização das variáveis de duração do armazenamento estático acontece antes
main()
de ser chamada e não na linha onde a declaração está localizada. E comoa
tem duração de armazenamento automática, não possui endereço atémain()
ser chamado. Nos sistemas convencionais,a
é alocado na pilha nesse ponto.A próxima coisa que temos que perceber é que não importa se
a
tem um endereço fixo, nem mesmo se o mudarmos parastatic int a;
. Porqueint * const ptr
não é uma constante de endereço , que é um termo formal para um certo tipo de expressão constante. C23 6.6:Agora espere um minuto...
int a
em main() ou&a
nenhuma das opções acima também. Então a linhana verdade também não está bem. O código funciona por causa de extensões definidas pela implementação em gcc/clang, mas não está estritamente em conformidade com C e não é portátil.
Simplesmente não faça isso durante a inicialização. Adicione uma tarefa.