Сомнительный синтаксис для доступа к содержимому массива
В некотором устаревшем коде, который я должен поддерживать, операторы & ставятся перед именами массивов всякий раз, когда массивы должны передаваться как (void *) аргументы
Вот простой пример:
char val = 42;
char tab[10];
memcpy(&tab, &val, 1);
Он компилируется с gcc или clang без ошибок и предупреждений. Это также дает ожидаемый результат.
Законен ли этот синтаксис?
Почему это работает?
Примечания: я обычно использую один из следующих синтаксисов:
memcpy(tab, &val, 1);
memcpy(&tab[0], &val, 1);
Эпилог:
В качестве дополнительного теста я использовал функцию, принимающую аргумент (char*) вместо (void *)
Я получаю следующее предупреждение, если пытаюсь скомпилировать с помощью clang:
warning: incompatible pointer types passing 'char (*)[10]' to parameter of type 'char *' [-Wincompatible-pointer-types]
Редактировать 1: В исходном примере вкладка была задана размером 1 элемент
Я просто изменил размер до 10 ради общности.
Редактировать 2: Как упоминалось в ответах, memcpy принимает (void *), а не (char*)
1 ответ
memcpy
параметры имеют тип void*
не char*
, Любой аргумент типа указателя (кроме указателей на функции) неявно преобразуется в void*
, Это правило особого случая, которое применяется только к void*
,
Учитывая декларацию
char tab[1];
или tab
или же &tab
действителен в качестве аргумента memcpy
, Они оценивают указатели разных типов (char*
а также char (*)[1]
), но оба указывают на одну и ту же область памяти; преобразование либо в void*
дает то же значение.
Для функции, которая на самом деле требует char*
только аргумент tab
является действительным; &tab
имеет неправильный тип. (Для переменной функции, такой как printf
или же scanf
возможно, компилятор не сможет обнаружить несоответствие типов.)