Передача аргументов массива по ссылке

#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).