2016-01-22 3 views
3

я перемещался вокруг стандарта «C», и я сталкивался с этим:Когда декларация идентификатора с областью блока имеет внутреннюю связь?

$ 6.7.9.5:

Если объявление идентификатора имеет блок сферы, а идентификатора имеет внешний или внутренний связь, декларация должна иметь , для которой нет идентификатора.

Так что мой вопрос касается названия. Мне также понравятся некоторые примеры, если это возможно.

ответ

1
static int i; // internal linkage 

void f() { 
    extern int i; // block-scope declaration; refers to i in global scope 
       // still internal linkage - see 6.2.2/4 
} 
0

Это означает следующее

#include <stdio.h> 

static int x = 1; 

int main() 
{ 
    int y = 2; 

    { 
     extern int x; 

     printf("x + y = %d\n", x + y); 
    } 
} 

Здесь внутри главной во внутреннем блоке переменная x имеет внутреннюю связь, и обозначает ту же переменную x, который определен вне главной.

Однако в этой программе

#include <stdio.h> 

static int x = 1; 

int main() 
{ 
    int y = 2; 
    int x = 3; 

    { 
     extern int x; 

     printf("x + y = %d\n", x + y); 
    } 
} 

переменной x объявляется с спецификатором extern имеет внешнюю связь, и это не то же самое, как переменные x определен перед главным. Причиной этого является то, что другая локальная переменная x скрывает глобальную переменную x, которая определена до main.

+0

Разве это не внешняя связь? Или, может быть, не потому, что 'x' уже объявлен. Это уловка здесь? – AnArrayOfFunctions

+0

@FISOCPP Нет, это внутренняя связь, потому что глобальный x определяется ключевым словом static. –

+0

@FISOCPP Он имел бы внешнюю связь, если переменная x, определенная до main, не была видна в блоке, где вторая переменная объявлена ​​с помощью спецификатора extern. –

0

Вы должны загрузить более новую версию стандарта C. Посмотрите на n1570.pdf, последний проект стандарта C11. Его язык является более явным:

6.2.2 Взаимосвязи идентификаторов

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

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

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

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

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

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

Смежные вопросы