Как объявить идентификатор с внутренней связью в области блока без предварительного объявления этого идентификатора с видимой некоторой связью?

Учти это:

#include <stdio.h>

static int b;

int main()
{
    {
        int b;

        {
            extern int b;

            b = 2;
        }
    }

    printf("%d", b);
}

Здесь по определению идентификатор b, которому присвоено значение 2, должен быть идентификатором с внешней связью. Однако по какой-то причине компилятор C clang не жалуется, и результат этого кода равен «2».

Я предполагаю это из-за точки $ 6.2.2.4 в стандарте C:

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

И поскольку предыдущее видимое объявление не указывает никакой связи ('int b').

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

Изменить: я вижу, что этот пример - UB, но это не меняет мой вопрос.


person AnArrayOfFunctions    schedule 24.01.2016    source источник
comment
Могу я спросить, за что было это голосование против?   -  person AnArrayOfFunctions    schedule 24.01.2016


Ответы (1)


Ваша программа имеет неопределенное поведение. У вас не может быть идентификатора с внутренней и внешней связью в одной и той же области.

C11, §6.2.3, 4 < / a> говорит

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

person P.P    schedule 24.01.2016
comment
Так как же этого не может быть? - person AnArrayOfFunctions; 24.01.2016
comment
Они не могут быть одним целым. Иметь внутреннюю и внешнюю связь для одного и того же идентификатора не имеет смысла (стандарт гласит, что это не определено). int b; (внутри внешнего блока внутри main()) не имеет связи. extern int b; объявляет b с внешней связью, которая конфликтует с static int b;, которая указывает внутреннюю связь. - person P.P; 24.01.2016
comment
Нет, я имел в виду, как моя примерная программа может не создавать UB без удаления переменной без привязки. Вы не отвечаете на мой вопрос. - person AnArrayOfFunctions; 24.01.2016
comment
Можете ли вы уточнить это? Нет, я имел в виду, как моя примерная программа может не создавать UB без удаления переменной без привязки? - person P.P; 24.01.2016
comment
Просто ответьте на мой вопрос в ОП. - person AnArrayOfFunctions; 24.01.2016
comment
Я не уверен, какую проблему вы пытаетесь решить. Один из способов доступа к переменной с внутренней связью - использовать указатель на нее: static int b; int *p = &b;, а затем использовать p для чтения / записи переменной с внутренней связью. С этим у вас может быть другой b без связи. Кроме этого, я не вижу никакого способа получить доступ к static int b; так, как вы хотите. - person P.P; 24.01.2016