Não é um comportamento indefinido , independentemente do que alguém, oficial ou não , diga, porque é definido pela norma. p->s
, exceto quando usado como um lvalue, é avaliado como um ponteiro idêntico a (char *)p + offsetof(struct T, s)
. Em particular, este é um char
ponteiro válido dentro do objeto malloc'd, e há 100 (ou mais, dependendo das considerações de alinhamento) endereços sucessivos imediatamente após ele, que também são válidos como char
objetos dentro do objeto alocado. O fato de que o ponteiro foi derivado usando em ->
vez de adicionar explicitamente o deslocamento ao ponteiro retornado por malloc
, convertido para char *
, é irrelevante.
Tecnicamente, p->s[0]
é o único elemento da char
matriz dentro da estrutura, os próximos elementos (por exemplo, p->s[1]
através p->s[3]
) são provavelmente bytes de preenchimento dentro da estrutura, que podem ser corrompidos se você executar a atribuição à estrutura como um todo, mas não se você simplesmente acessar um indivíduo membros e o resto dos elementos são espaço adicional no objeto alocado que você pode usar como quiser, desde que obedeça aos requisitos de alinhamento (e char
não tenha requisitos de alinhamento).
Se você está preocupado com a possibilidade de sobreposição com bytes de preenchimento na estrutura, de alguma forma, invocar demônios nasais, pode evitar isso substituindo o 1
in [1]
por um valor que garante que não haja preenchimento no final da estrutura. Uma maneira simples, mas inútil de fazer isso, seria fazer uma estrutura com membros idênticos, exceto nenhum array no final, e usar s[sizeof struct that_other_struct];
para o array. Então, p->s[i]
é claramente definido como um elemento da matriz na estrutura para i<sizeof struct that_other_struct
e como um objeto char em um endereço após o final da estrutura para i>=sizeof struct that_other_struct
.
Edit: Na verdade, no truque acima para obter o tamanho certo, você também pode precisar colocar uma união contendo cada tipo simples antes da matriz, para garantir que a própria matriz comece com o alinhamento máximo, em vez de no meio do preenchimento de algum outro elemento . Novamente, eu não acredito que nada disso seja necessário, mas estou oferecendo isso para o mais paranóico dos advogados de línguas por aí.
Edição 2: A sobreposição com bytes de preenchimento definitivamente não é um problema, devido a outra parte do padrão. C requer que, se duas estruturas concordam em uma subsequência inicial de seus elementos, os elementos iniciais comuns podem ser acessados por meio de um ponteiro para qualquer tipo. Como consequência, se uma estrutura idêntica a, struct T
mas com uma matriz final maior, fosse declarada, o elemento s[0]
teria que coincidir com o elemento s[0]
em struct T
, e a presença desses elementos adicionais não poderia afetar ou ser afetada pelo acesso a elementos comuns da estrutura maior usando um ponteiro para struct T
.