Advertencia extraña en una función C const argumento de matriz multidimensional

Recibo algunas advertencias extrañas sobre este 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 salida de la siguiente manera:

$ 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]'

Si defino la función como:

void mprod4(mat4 r, mat4 a, mat4 b)
{
}

O definiendo matrices en main como:

mat4 mr;
const mat4 ma;
const mat4 mb;

O llame a la función en main como:

mprod4(mr, (const double(*)[4])ma, (const double(*)[4])mb);

O incluso definiendomat4 como:

typedef double mat4[16];

Hace que la advertencia desaparezca. ¿Que está sucediendo aquí? ¿Estoy haciendo algo inválido?

La versión de gcc es 4.4.3, si es relevante.

También publiqué en gcc bugzilla:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47143

Mi solución actual es hacer macros feas que arrojan cosas para mí:

#ifndef _NO_UGLY_MATRIX_MACROS

#define mprod4(r, a, b) mprod4(r, (const double(*)[4])a, (const double(*)[4])b)

#endif

Respuesta de Joseph S. Myers en gcc bugzilla:

No es un error Los parámetros de la función son de tipo "puntero a matriz [4] de const double" porque const en un tipo de matriz se aplica al tipo de elemento, recursivamente, y luego el tipo de matriz más externo, solo, de un parámetro de tipo de matriz decae a un puntero , y los argumentos pasados son del tipo "puntero a matriz [4] de doble" después de la descomposición de matriz a puntero, y el único caso en el que se permite agregar calificadores en la asignación, pasar argumentos, etc. es calificadores en el puntero inmediato objetivo, no aquellos anidados más profundamente.

Me suena bastante confuso, como la función espera:

pointer to array[4] of const doubles

y estamos pasando

pointer to const array[4] of doubles

intead

¿O sería lo contrario? Las advertencias sugieren que la función espera un:

const double (*)[4]

lo cual me parece más como un

pointer to const array[4] of doubles

Estoy realmente confundido con esta respuesta. ¿Podría alguien que comprende lo que dijo aclarar y ejemplificar?

Respuestas a la pregunta(6)

Su respuesta a la pregunta