путаница c c - PullRequest
       29

путаница c c

4 голосов
/ 14 марта 2011

Я программист среднего уровня C. Я шел через простой фрагмент кода в C

int a ; // A
const int b; // B
static int c; //C
void func(int d) // D
{
   //.....
}

Какова связь переменных a, b, c и d. Я совершенно уверен, что a по умолчанию имеет внешнюю связь, b, c и d имеют внутреннюю связь. Правильно ли мое понимание?

Это мой первый вопрос на этом сайте.

Ответы [ 4 ]

6 голосов
/ 14 марта 2011

Из раздела 6.2.2, Linkages of identifiers, C99, окончательный источник:

1 / Идентификатор, объявленный в разных областях или в одной и той же области более одного раза, может быть сделано для ссылки на тот же объект или функцию с помощью процесса, называемого связью. Есть три вида связи: внешняя, внутренняя и нет.

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

3 / Если объявление идентификатора области файла для объекта или функции содержит статический спецификатор класса хранения, идентификатор имеет внутреннюю связь.

4 / Для идентификатора, объявленного с помощью спецификатора класса хранения extern в области видимости, в которой видно предыдущее объявление этого идентификатора, если в предыдущем объявлении указана внутренняя или внешняя связь, связь идентификатора в последующем объявлении такой же, как связь, указанная в предыдущей декларации. Если никакое предыдущее объявление не видно или если в предыдущем объявлении не указана связь, то идентификатор имеет внешнюю связь.

5 / Если объявление идентификатора для функции не имеет спецификатора класса хранения, его связь определяется точно так, как если бы он был объявлен с помощью спецификатора класса хранения extern. Если объявление идентификатора для объекта имеет область действия файла и не имеет спецификатора класса хранения, его связь является внешней.

6 / Следующие идентификаторы не имеют связи: идентификатор, объявленный как что-либо, кроме объекта или функции; идентификатор, объявленный как параметр функции; идентификатор области блока для объекта, объявленного без спецификатора класса хранения extern.

7 / Если внутри единицы перевода появляется один и тот же идентификатор с внутренней и внешней связью, поведение не определено.

Теперь рассмотрим ваши переменные одну за другой:

  • a рассматривается в части 5, поскольку это «идентификатор объекта [который] имеет область файла и не имеет спецификатора класса хранения». Поэтому он имеет внешнюю связь.
  • b также охватывается частью 5 (область действия файла, без спецификатора класса хранения). Отсюда и внешняя связь.
  • c охватывается частью 3, поскольку он имеет спецификатор класса хранения static - он имеет внутреннюю связь.
  • наконец, d охватывается частью 6, являясь параметром функции - он не имеет связи.
4 голосов
/ 14 марта 2011

В C, a и b имеют внешнюю связь, а c имеет внутреннюю связь.В C ++ вы были бы правы, что b также будет иметь внутреннюю связь.

Для случая "D" я не уверен, о чем вы говорите: функция или параметр.func имеет внешнюю связь;d не имеет связи.

3 голосов
/ 14 марта 2011

Я вполне уверен, что по умолчанию имеет внешнюю связь, b, c и d имеют внутреннюю связь. Правильно ли мое понимание?

Нет! d не имеет никакой связи, потому что это формальный параметр.

из C99

Следующие идентификаторы имеют без связи : идентификатор, объявленный как что-либо, кроме объекта или функции; идентификатор, объявленный как параметр функции ; идентификатор области блока для объекта, объявленного без спецификатора класса хранения extern.

Кроме того, b имеет внешнюю связь в C99. В C ++ константные переменные в области видимости файла имеют внутреннюю связь.

0 голосов
/ 14 марта 2011

a, b и c имеют одинаковую связь, если они объявлены в глобальной области видимости, что они

d - это параметр функции, который создается при вызове этой функции и больше не существует, когда функция возвращает

...