Aviso estranho em uma função C const argumento de matriz multidimensional
Estou recebendo alguns avisos estranhos sobre esse código:
typedef double mat4[4][4];
void mprod4(mat4 r, const mat4 a, const mat4 b)
{
/* yes, function is empty */
}
int main()
{
mat4 mr, ma, mb;
mprod4(mr, ma, mb);
}
gcc
saída da seguinte forma:
$ gcc -o test test.c
test.c: In function 'main':
test.c:13: warning: passing argument 2 of 'mprod4' from incompatible pointer
type
test.c:4: note: expected 'const double (*)[4]' but argument is of type 'double
(*)[4]'
test.c:13: warning: passing argument 3 of 'mprod4' from incompatible pointer
type
test.c:4:
note: expected 'const double (*)[4]' but argument is of type 'double
(*)[4]'
Se eu definir a função como:
void mprod4(mat4 r, mat4 a, mat4 b)
{
}
Ou definindo matrizes em main como:
mat4 mr;
const mat4 ma;
const mat4 mb;
Ou chame a função em main como:
mprod4(mr, (const double(*)[4])ma, (const double(*)[4])mb);
Ou mesmo definindomat4
Como:
typedef double mat4[16];
Faz o aviso desaparecer. O que esta acontecendo aqui? Estou fazendo algo inválido?
A versão do gcc é 4.4.3, se relevante.
Também publiquei no gcc bugzilla:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47143
Minha solução atual é criar macros feias que lançam coisas para mim:
#ifndef _NO_UGLY_MATRIX_MACROS
#define mprod4(r, a, b) mprod4(r, (const double(*)[4])a, (const double(*)[4])b)
#endif
Resposta de Joseph S. Myers no gcc bugzilla:
Não é um bug. Os parâmetros de função são do tipo "ponteiro para o array [4] de const double" porque const em um tipo de array se aplica ao tipo de elemento, recursivamente, e depois ao tipo de array mais externo, apenas, de um parâmetro do tipo de array decai para um ponteiro , e os argumentos passados são do tipo "ponteiro para o array [4] de duplo" após decaimento do array para o ponteiro, e o único caso em que os qualificadores podem ser adicionados à atribuição, passagem de argumentos etc. são qualificadores no ponteiro imediato alvo, não aqueles aninhados mais profundamente.
Parece bastante confuso para mim, como a função espera:
pointer to array[4] of const doubles
e nós estamos passando
pointer to const array[4] of doubles
intead.
Ou seria o inverso? Os avisos sugerem que a função espera a:
const double (*)[4]
o que me parece mais um
pointer to const array[4] of doubles
Estou realmente confuso com esta resposta. Alguém que entenda o que ele disse pode esclarecer e exemplificar?