#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
. Код становится корректным.