#c #arrays #pass-by-reference
#c #массивы #передача по ссылке
Вопрос:
Я наткнулся на функцию с такой подписью.
void foo(char (amp;x)[5])
{
}
Это синтаксис для передачи массива символов фиксированного размера по ссылке.
Тот факт, что для этого требуются круглые скобки amp;x
, кажется мне необычным.
Вероятно, это часть стандарта C 03.
Как называется эта форма и может ли кто-нибудь указать ссылку на стандарт?
c decl еще не друг:
$ c decl
Type `help' or `?' for help
c decl> explain void foo(char (amp;x)[5])
syntax error
Комментарии:
1. Я не могу указать на стандарт, но я считаю, что это потому
charamp; x[5]
, что это массив из 5 символьных ссылок, а не ссылка на массив символов длиной 5.2. 8.3.2 Ссылки «Не должно быть ссылок на ссылки, никаких массивов ссылок и никаких указателей на ссылки».
3. Разве это не был действительно отличный призыв использовать знаки препинания для таких функций.
Ответ №1:
В синтаксисе нет ничего необычного или нового. Вы постоянно видите это в C с указателями. []
имеет более высокий приоритет, чем amp;
, поэтому вам нужно заключить его в круглые скобки, если вы хотите объявить ссылку на массив. То же самое происходит с *
(который имеет тот же приоритет, amp;
что и): например, чтобы объявить указатель на массив из 5 символов в C, вы должны сделать char (*x)[5];
. Аналогично, указатель на функцию, которая принимает и возвращает значение int, будет int (*x)(int);
( ()
имеет тот же приоритет, []
что и ). Со ссылками та же история, за исключением того, что ссылки есть только на C , и существуют некоторые ограничения на то, какие типы могут быть сформированы из ссылок.
Комментарии:
1. 1 За объяснение требования к скобкам. Где задокументированы ограничения на формирование типов из ссылок?
2. @Eddy Pronk: я имел в виду утверждение, которое вы процитировали в своем комментарии к вашему вопросу выше
Ответ №2:
Здесь нечего объяснять, это просто то, как работают правила синтаксического анализа для объявлений в C :
char amp; x[5] // declare x as array 5 of reference to char (not valid C !)
char (amp;x)[5] // declare x as reference to array 5 of char
Внимание: первая версия недопустима для C , поскольку у вас не может быть массивов ссылок. Это просто объяснение синтаксиса объявления. (Извините, что так долго разбирался в этом, и спасибо за полезные комментарии!)
Вам разрешено заключать идентификатор типа в произвольные круглые скобки, если хотите, поэтому вы также можете сказать char amp;(x)[5]
(первый случай) или char (((amp;x)))[5]
(второй случай).
Комментарии:
1. Какой компилятор принимает первую форму? gcc 4.4.5 не выполняет: ошибка: объявление ‘x’ как массива ссылок
2. За исключением, конечно, того, что первый не является законным C , поскольку вам не разрешено иметь массивы ссылок.
3. Кажется, вам необходимо заключить хотя бы один уровень круглых скобок.
4. @JamesKanze: не как самостоятельные объявления, а как объявления аргументов функции! Хороший момент 🙂
5. Сравните
void (*funcptr)(int)
, чтобы объявить указатель на функцию, а не функцию, которая возвращает указатель.
Ответ №3:
c decl
в основном работает для этого. Это просто немного придирчиво к тому, что вы ему даете.
c decl> explain void foo(char (amp;)[5])
declare foo as function (reference to array 5 of char) returning void
c decl> explain void foo(char amp;[5])
declare foo as function (array 5 of reference to char) returning void
Как отмечалось в другом ответе, массив ссылок является незаконным. Компилятор GNU C сообщает:
ошибка: объявление ‘x’ как массива ссылок
Кстати, вот ссылка на онлайн-утилиту, которая обслуживает cdecl
(хотя она жалуется на ссылки, потому что версия, размещенная на сайте, зависит от C).