Pode int (*)[]
ser um tipo incompleto?
C 2018 6.2.5 1 diz:
Em vários pontos dentro de uma unidade de tradução, um tipo de objeto pode estar incompleto (sem informações suficientes para determinar o tamanho dos objetos desse tipo) ou completo (com informações suficientes).
Assim, parece que, se o tamanho de um tipo for conhecido, o tipo estará completo. 6.2.6.1 28 especifica que certos tipos de ponteiros devem ter os mesmos tamanhos (ponteiros void
e caracteres, ponteiros para tipos compatíveis, ponteiros para estruturas e ponteiros para uniões), mas os ponteiros para outros tipos podem variar.
Em uma implementação C em que todos os ponteiros, ou todos os ponteiros para matrizes de int
, têm o mesmo tamanho, o tamanho de int (*)[]
é conhecido e, portanto, seria completo. Em uma implementação que, digamos, usa ponteiros diferentes para matrizes grandes, o tamanho não seria conhecido e, portanto, está incompleto.
Como MM aponta , uma estrutura não deve conter um membro com tipo incompleto, exceto um membro de matriz flexível final, de acordo com uma restrição em 6.7.2.1 3. Isso sugere que uma implementação com um tamanho de ponteiros deve aceitar struct { int (*p)[]; }
enquanto uma implementação que tenha diferentes tamanhos para essas matrizes devem diagnosticar uma violação de restrição. (Isso, por sua vez, significa que tal declaração não faz parte do estritamente conforme C.)
fonte
void *
concluir mostra que um ponteiro para um tipo incompleto pode ser concluído. Não mostra se um ponteiro para um tipo incompleto pode ou não estar incompleto. Se alguém perguntasse “Um mamífero pode ser um elefante?”, Mostrar que “Um leão é um mamífero” não forneceria que um mamífero não possa ser um elefante. A pergunta pergunta se o conjunto X de ponteiros para o tipo incompleto pode conter um elemento incompleto. Mostrar que o conjunto X de ponteiros para o tipo incompleto contém um elemento que é concluído é irrelevante.Respostas:
Uma matriz de tamanho desconhecido está incompleta:
O tipo,
int (*)[]
no entanto, não está incompleto: é um ponteiro de uma matriz deint
tamanho desconhecido.E um ponteiro tem um tamanho bem conhecido:
Além disso, você pode até tirar a referência dele, graças à semântica da matriz:
Editar
Além disso, um ponteiro é sempre um tipo completo. Está escrito preto no branco em 6.2.5 / 20:
fonte
printf
mostra apenas que um ponteiro para uma matriz incompleta está completo na implementação em que foi executado, conforme declarado na pergunta - se não fosse o 6.2.5 20, citado no último parágrafo, ele pode falhar na compilação. 6.2.5 23 também não é relevante; nos diz que o tamanho é conhecido e constante, se estiver completo, e já sabemos que estar completo significa que o tamanho é conhecido.int
devem ter o mesmo tamanho um do outro e todos os ponteiros para matrizes de um certostruct
tamanho devem ter o mesmo tamanho, embora talvez nem todos os ponteiros para matrizes de tipos diferentesstruct
devam ter o mesmo tamanho como um ao outro.T(*)[]
deve ter o mesmo tamanho queT(*)[5]
, uma vez que são tipos compatíveis e poderíamos adicionar ou remover qualificadores