Пример области видимости прототипа функции

#c #function #scope #declaration #function-declaration

#c #функция #область видимости #объявление #объявление функции

Вопрос:

Существует определение области прототипа функции (3.3.4 / 1 N3797):

В объявлении функции или в любом деклараторе функций, кроме декларатора определения функции (8.4), имена параметров (если они указаны) имеют область видимости прототипа функции, которая заканчивается в конце ближайшего окружающего декларатора функции.

Можем ли мы получить пример, описывающий это правило?

Комментарии:

1. Не уверен, какой пример вы ищете. Объявление функции — это очень простая конструкция. Область видимости прототипа функции означает, что эти параметры видны до тех пор, пока объявление функции можно считать закрытым (надеюсь, я не неправильно истолковываю стандарт). Это означает, например, что у вас не может быть двух параметров с одинаковым именем.

2. @AndreaLaforgia Я ищу пример, четко показывающий область видимости.

3. @AndreaLaforgia Этот вопрос является прекрасным примером того, как стандарт может усложнить даже самые простые концепции.

4. @DmitryFucintv Вам действительно следует обновить свой профиль, сообщив, что вы создаете компилятор c

Ответ №1:

Вот простой пример

 int a;

void f( int a, int a );
  

Компилятор выдаст ошибку для второго параметра a, поскольку его имя совпадает с именем первого параметра. То есть компилятор сообщит, что произошло переопределение имени a . Одно и то же имя определяется дважды в одной и той же области.

Или другой пример

 struct A {};

void f( int A, struct A );
  

Имя первого параметра скрывает имя структуры, поэтому второй параметр определяется с использованием разработанного имени структуры.

Комментарии:

1. Я думаю, что первый int a; в вашем примере может вводить в заблуждение. Для того, чтобы компилятор сообщал о повторяющемся имени в прототипе, вам не нужно объявлять эту переменную.

2. @Andrea Laforgia Это показывает, что прототипы функций имеют свои собственные области объявления, а имя в прототипе функции может скрывать имя во внешней области объявления. Было бы лучше, если бы я использовал первый объект в качестве аргумента функции по умолчанию. Но у меня не было много времени, чтобы написать подробный ответ.

Ответ №2:

Вот пример, который включает относительно редкую, но иногда встречающуюся ошибку

 void foo(struct S *v);

struct S {
  int i;
};

int main() {
  struct S *p = 0;
  foo(p);           // ERROR: incompatible pointer types
}
  

Приведенный выше код неверно сформирован (если позаимствовать термин C ), поскольку struct S еще не известен на момент объявления foo . По этой причине struct S внутри прототипа foo интерпретируется как прямое объявление нового типа. Он имеет область видимости прототипа функции. Он выходит за пределы области видимости, как только прототип заканчивается. Это означает, что объявление struct S внутри foo прототипа полностью не связано с объявлением struct S , которое следует за ним. Это два разных типа. Указатель p внутри main несовместим с типом параметра foo . Код неверно сформирован.

Обратите внимание, что если вы поменяете местами объявление struct S и прототип foo , объявление struct S внутри прототипа w больше не является прямым объявлением. Предполагается, что он ссылается на ранее объявленный struct S . Код становится корректным.