Eu tenho esta estrutura:
typedef struct {
int *array;
int first;
int last;
} arguments;
e eu estaria interessado em ter uma estrutura diferente com alguns argumentos adicionados:
typedef struct {
int *array;
int first;
int last;
// only used in children
int read_fd;
int write_fd;
} child_arguments;
mas tenho algumas funções que esperamarguments
void do_something(arguments* args) { ... }
É seguro fazer esse tipo de gesso:
void do_something_in_child(child_arguments* child_args) {
do_something( (arguments*) child_args );
}
Imagino que, como C não reordena membros em uma struct, e elementos adicionados depois não devem afetar o preenchimento de elementos antigos, isso pode ser seguro. Mas é? E se for, é compatível com C ou é um comportamento tecnicamente indefinido, mas seguro na maioria dos compiladores?
É um comportamento indefinido converter de um ponteiro de um tipo para um ponteiro de outro tipo incompatível e, posteriormente, desreferenciar esse ponteiro.
Entretanto, se você tiver uma união dessas duas estruturas, você terá permissão para acessar qualquer um dos membros iniciais comuns de qualquer membro da união.
Então, fazer isso seria permitido:
@dbush postou uma resposta sobre uma maneira de resolver isso por meio da regra da sequência inicial comum e uniões.
Outra maneira, que talvez seja mais robusta e confiável em termos de suporte do compilador, é fazer com que uma struct declare uma instância da outra struct como seu primeiro membro. Como se vê, essa é a maneira recomendada de implementar herança e polimorfismo em C, o que parece ser o que você está fazendo.
Existe esta regra encontrada no padrão C23 atual abaixo de 6.7.3.2:
Isso nos permite converter livremente de um ponteiro para uma struct e um ponteiro para o primeiro item na struct. Essa regra remonta ao primeiro padrão C e os compiladores a suportam desde uma época anterior aos desastres de aliasing estrito se tornarem comuns no início dos anos 2000.
(O único problema menor é que C na verdade não especifica "convertido adequadamente", embora isso seja um problema de qualidade de implementação e todos os compiladores que usei o interpretem como "convertido explicitamente para o tipo de ponteiro correspondente".)
Confira estas perguntas e respostas para alguns exemplos de como fazer isso: Como implementar polimorfismo em C?