Estou analisando o rascunho C2Y n3467 e tentando entender algo envolvendo funções que utilizam VLAs.
Parece haver um comportamento indefinido que não é mencionado pela norma. Ou seja:
- passando uma matriz multidimensional de uma extensão particular para
- um parâmetro de função esperando um, onde
- a definição da função espera uma extensão diferente.
Aqui está meu código demonstrando isso. Embora o comportamento resultante tenha feito sentido, não entendo ( Q :) por que o padrão nunca declarou esse comportamento indefinido/não especificado/definido pela implementação. Nas seções específicas, 6.7.7.3. Array e 6.7.7.4. Declaradores de Função na seção 6.7. Declaração, e 6.9.2. Definições de Função na seção Declarações Externas, a possível UB não é mencionada em nenhum lugar nesses lugares.
#include <stdio.h>
#include <stdlib.h>
extern int d, e;
int g(int z[3][*][*]);
int main()
{
int z[3][d][e];
for(int i=0; i<3; i++)
for(int j=0; j<d; j++)
for(int k=0; k<e; k++)
z[i][j][k] = i*d*e+j*e+k;
int x = g(z);
printf("%zd, %d.\n", sizeof(float[x]), x);
return 0;
}
extern int u, v;
int g(int z[3][v][u])
{
return z[0][2][2];
}
As variáveis externas são definidas assim:
int u = 3, v = 5;
int d = 7, e = 7;
Saída:
32, 8.
A seção 6.5.3.3 parágrafo 6 descreve como os argumentos são convertidos em uma chamada de função:
Após a conversão de array para ponteiro e o ajuste automático dos tipos de argumentos de função declarados,
g(z)
chama uma função com parâmetro do tipoint (*)[v][u]
, passando um argumento do tipoint (*)[d][e]
. O tipo do argumento é convertido para o tipo do parâmetro como se fosse uma atribuição.Então, está tudo bem em executar essa tarefa?
Bem, as restrições à atribuição são descritas na seção 6.5.17.2, parágrafo 1. A seção relevante é a seguinte:
Portanto, esses ponteiros precisam apontar para versões qualificadas ou não qualificadas de tipos compatíveis. Será que é isso mesmo?
Bem, a seção 6.7.7.3 parágrafo 6 diz o seguinte:
Os tipos de array
int [v][u]
eint [d][e]
estão sendo usados em um contexto que exige compatibilidade, mas os especificadores de tamanho não correspondem. O comportamento é indefinido.