Странное предупреждение в функции C const аргумент многомерного массива

Я получаю несколько странных предупреждений об этом коде:

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 выводит следующее:

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

Если я определяю функцию как:

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

Или определяю матрицы в основном как:

mat4 mr;
const mat4 ma;
const mat4 mb;

Или вызовите функцию в main как:

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

Или даже определив mat4 как:

typedef double mat4[16];

Удаляет предупреждение. Что здесь происходит? Я делаю что-то недопустимое?

Версия gcc - 4.4.3, если уместно.

Я также написал на gcc bugzilla: http://gcc.gnu.org/bugzilla/show_bug.cgi?id = 47143

Мой текущий обходной путь - создание уродливых макросов, которые меняют содержимое:

#ifndef _NO_UGLY_MATRIX_MACROS

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

#endif

Ответ Джозефа С. Майерса на gcc bugzilla:

Это не ошибка. Параметры функции имеют тип "указатель на массив [4] из const double "потому что const на тип массива применяется к элементу рекурсивно, а затем только самый внешний тип массива параметр типа массива распадается на указатель, и переданные аргументы типа "указатель на массив [4] из double "после распада массива на указатель, и единственный случай, когда квалификаторы разрешено добавлять в задание, передача аргументов и т. д. - это квалификаторы непосредственная цель указателя, а не те, которые вложены более глубоко.

Звучит довольно запутанно, как и ожидает функция:

pointer to array[4] of const doubles

и мы передаем

pointer to const array[4] of doubles

intead.

Или это будет наоборот? Предупреждения предполагают, что функция ожидает:

const double (*)[4]

, который мне кажется больше похожим на

pointer to const array[4] of doubles

. Я действительно смущен этим ответом. Может ли кто-нибудь, кто понимает то, что он сказал, прояснить и проиллюстрировать?

7
задан SmokeDetector 13 December 2017 в 02:13
поделиться