Объявление функциональных статических и более поздних непомех: действительно ли это стандартно?

Я заметил очень любопытное поведение, что, если бы стандартный, я буду очень рад использовать (то, что я хотел бы сделать с ним, довольно сложно для объяснения и не важный вопросу).

Поведение:

static void name();
void name() {
    /* This function is now static, even if in the declaration
     * there is no static keyword. Tested on GCC and VS. */
}

То, чему любопытно, - то, что инверсия производит ошибку времени компиляции:

void name();
static void name() {
    /* Illegal */
}

Так, действительно ли это стандартно, и я могу ожидать, что другие компиляторы будут вести себя тот же путь?Спасибо!

6
задан Thomas Bonini 22 December 2009 в 02:20
поделиться

2 ответа

C++ стандарт:

7.1.1/6: "Имя, объявленное в области пространств имен без a критерий класса хранилища-спецификатор имеет внешний связь, если она не имеет внутренней связи из-за предыдущего объявления" [или если оно не конст.]

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

Инверсия запрещена, поскольку:

7.1.1/7: "Связи, подразумеваемые последовательными декларациями для данного сущность согласна"

Итак, во втором примере первое заявление имеет внешнюю связь (по пункту 7.1.1/6), а второе - внутреннюю (явно), и они не согласны.

Вы также спрашиваете о языке C, и я полагаю, что это одно и то же. Но у меня есть книга на Си++ прямо здесь, в то время как вы можете искать в черновике стандарта на Си онлайн так же, как и я ;-)

.
12
ответ дан 8 December 2019 в 16:03
поделиться

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

Так что во втором случае отсутствие статического на прототипе означало, что функция была определена как НЕ статическая, а затем, когда она была позже объявлена как статическая, это было ошибкой.

Если бы вы оставили тип возврата в прототипе, то по умолчанию было бы int, и тогда вы бы снова получили ошибку с типом возврата void. То же самое происходит с __crtapi и __stdcall и __declspec() (в компиляторе Microsoft C).

.
3
ответ дан 8 December 2019 в 16:03
поделиться