Здравствуйте, DirtyGarry, Вы писали:
DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
extern означает вполне конкретное связывание: внешнее
почему вы решили, что это не так?
Здравствуйте, DirtyGarry, Вы писали:
DG>Уважаемые коллеги, помогите прояснить ситуацию.
DG>Для переменной, объявленной на уровне файла, выражение
DG>
DG>extern int i;
DG>
DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
Неверно.
extern — это только объявление имени. Сам объект должен быть определен.
Время жизни, тип связывания, область видимости задается определением.
В данном случае определение стоит после использования.
В определении слово static — объявлено по стандарту устаревшим.
Ранее оно определяло "локальность" объекта в данном файле.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
DG>>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение). LVV>Неверно. LVV>extern — это только объявление имени. Сам объект должен быть определен. LVV>Время жизни, тип связывания, область видимости задается определением. LVV>В данном случае определение стоит после использования. LVV>В определении слово static — объявлено по стандарту устаревшим. LVV>Ранее оно определяло "локальность" объекта в данном файле.
пардон — я о С++...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
И вот чего минусуют? Вопрос то интересный. В принципе компилятор, увидев, что i объявлена как extern, должен этим удовлетвориться. Линковщик тоже не должен ругаться, так как в единице трансляции есть переменная i. Так вот VS2008 C с этим согласен, а вот GCC нет, и именно на этапе компиляции, пишет static declaration of ‘i’ follows non-static declaration В принципе их обоих можно понять, они оба правы, но более прав мне кажется все-таки GCC, слишком неоднозначная и опасная такая конструкция.
ЗЫ Стандарт бы достать да почитать, но лень..
Буду признателен, если Вы поясните мне цитату, которая приведена ниже.
1. Как понимать "? linkage".
2. О чем идет речь в последнем абзаце?
Спасибо.
K.N. King "C programming. A modern approach.", стр. 463
A variable in an extern declaration always has static storage duration. The scope of the variable depends on the declaration’s placement. If the declaration is inside a block, the variable has block scope, otherwise, it has file scope:
Determine the linkage of an extern variable is a bit harder. If the variable was declared static earlier in the file (outside of any function definition), then it has internal linkage. Otherwise (the normal case), the variable has external linkage.
Здравствуйте, koenjihyakkei, Вы писали:
K>И вот чего минусуют? Вопрос то интересный.
Потому что это разжёвано в книгах. Просто надо внимательно почитать и выяснить значения непонятных терминов вроде области видимости, жизни, единицы трансляции, компоновки, ODR, объявления и определения. Это всё описано в Ритчи.
Здравствуйте, Kernan, Вы писали:
K>Потому что это разжёвано в книгах. Просто надо внимательно почитать и выяснить значения непонятных терминов вроде области видимости, жизни, единицы трансляции, компоновки, ODR, объявления и определения. Это всё описано в Ритчи.
Где конкретно там это разжевано? Именно данный случай конфликта двух этих классов памяти в одном файле? Я открывал книгу, пробежался поиском, никакого разжевывания не увидел. Плюс почему в 2008 студии код прошел? Понятно, что мелокософты на сишный компилер давно забили, но С89 он вроде как полностью поддерживает, а книга Ритчи как раз о нем..
Здравствуйте, DirtyGarry, Вы писали:
DG>Для переменной, объявленной на уровне файла, выражение DG>
DG>extern int i;
DG>
DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
Тут главное помнить, что у C и C++ связывание может различаться. Лаптев, например, уже "попался".
Это внешнее связывание (т.к. оно первое):
Committee Draft — May 6, 2005
6.2.2 Linkages of identifiers
4 For an identifier declared with the storage-class specifier extern in a scope in which a
prior declaration of that identifier is visible,23) if the prior declaration specifies internal or
external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external linkage.
DG>Если связывание непонятно какое, я предположил, что программа DG>
DG>extern int i;
DG>void f(void)
DG>{
DG> i = i + 5;
DG>}
DG>static int i;
DG>
DG>скомпилируется. Но компилятор (gcc) со мной не согласился. DG>Подскажите, пожалуйста, где я ошибся в своих рассуждениях.
Первая декларация объявляет внешнее связывание, последняя — внутренние. Согласно
6.2.2/7 If, within a translation unit, the same identifier appears with both internal and external
linkage, the behavior is undefined.
это неопределённое поведение. Т.е. даже если соберётся, то ничего не гарантировано.
Я не знаю как там в окончательном стандарте, но я бы требовал диагностику, а не это убойное UB.
DG>Приведенный пример, видимо, можно исправить только переместив определение переменной i в начало файла.
Если же такой порядок:
static int i;
extern int i;
то, согласно первой цитате (6.2.2/4) связывание у i — внутреннее.