[C] extern и связывание
От: DirtyGarry  
Дата: 09.10.14 08:52
Оценка: 5 (1) -2
Уважаемые коллеги, помогите прояснить ситуацию.

Для переменной, объявленной на уровне файла, выражение

extern int i;


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

Если связывание непонятно какое, я предположил, что программа

extern int i;

void f(void)
{
    i = i + 5;
}

static int i;


скомпилируется. Но компилятор (gcc) со мной не согласился.

Подскажите, пожалуйста, где я ошибся в своих рассуждениях.

Приведенный пример, видимо, можно исправить только переместив определение переменной i в начало файла.
Re[4]: [C] extern и связывание
От: uzhas Ниоткуда  
Дата: 09.10.14 11:36
Оценка: 2 (1)
Здравствуйте, uzhas, Вы писали:

U>если коротко, то в C11 extern может сохранять linkage, только если он уже объявлен выше


кстати, ваша цитата об этом и говорит:
1.

If the variable was declared static earlier in the file (outside of any function definition), then it has internal linkage.

2.

Otherwise (the normal case), the variable has external linkage.


3. если же ниже указан static, то это UB. гцц ведет себя корректно: прерывает компиляцию
Отредактировано 09.10.2014 11:37 uzhas . Предыдущая версия .
Re: [C] extern и связывание
От: koenjihyakkei Россия  
Дата: 09.10.14 10:15
Оценка: +1
Здравствуйте, DirtyGarry, Вы писали:

И вот чего минусуют? Вопрос то интересный. В принципе компилятор, увидев, что i объявлена как extern, должен этим удовлетвориться. Линковщик тоже не должен ругаться, так как в единице трансляции есть переменная i. Так вот VS2008 C с этим согласен, а вот GCC нет, и именно на этапе компиляции, пишет static declaration of ‘i’ follows non-static declaration В принципе их обоих можно понять, они оба правы, но более прав мне кажется все-таки GCC, слишком неоднозначная и опасная такая конструкция.
ЗЫ Стандарт бы достать да почитать, но лень..
Re: [C] extern и связывание
От: uzhas Ниоткуда  
Дата: 09.10.14 09:04
Оценка:
Здравствуйте, DirtyGarry, Вы писали:

DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).


extern означает вполне конкретное связывание: внешнее
почему вы решили, что это не так?
Re: [C] extern и связывание
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 09.10.14 09:05
Оценка:
Здравствуйте, DirtyGarry, Вы писали:

DG>Уважаемые коллеги, помогите прояснить ситуацию.

Купи книжку Кернигана и Ритчи "Язык программирования С"
Автор(ы): Брайан Керниган, Деннис Ритчи
Издательство: Вильямс
Цена: 256р.

Классическая книга по языку С, написанная самими разработчиками этого языка и выдержавшая в США уже 34 переиздания! Книга является как практически исчерпывающим справочником, так и учебным пособием по самому распространенному языку

DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
Нет. Читай книгу по языку.
http://msdn.microsoft.com/en-us/library/0603949d.aspx
Sic luceat lux!
Re: [C] extern и связывание
От: LaptevVV Россия  
Дата: 09.10.14 09:11
Оценка:
Здравствуйте, DirtyGarry, Вы писали:

DG>Уважаемые коллеги, помогите прояснить ситуацию.


DG>Для переменной, объявленной на уровне файла, выражение


DG>
DG>extern int i;
DG>

DG>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
Неверно.
extern — это только объявление имени. Сам объект должен быть определен.
Время жизни, тип связывания, область видимости задается определением.
В данном случае определение стоит после использования.
В определении слово static — объявлено по стандарту устаревшим.
Ранее оно определяло "локальность" объекта в данном файле.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: [C] extern и связывание
От: LaptevVV Россия  
Дата: 09.10.14 09:12
Оценка:
Здравствуйте, LaptevVV, Вы писали:

DG>>
DG>>extern int i;
DG>>

DG>>«дает» глобальное время жизни, файловую область видимости и непонятно какое связывание (потому что это не определение).
LVV>Неверно.
LVV>extern — это только объявление имени. Сам объект должен быть определен.
LVV>Время жизни, тип связывания, область видимости задается определением.
LVV>В данном случае определение стоит после использования.
LVV>В определении слово static — объявлено по стандарту устаревшим.
LVV>Ранее оно определяло "локальность" объекта в данном файле.
пардон — я о С++...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: [C] extern и связывание
От: wander  
Дата: 09.10.14 10:09
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>В определении слово static — объявлено по стандарту устаревшим.

Его уже раздепрекейтили.
Re[2]: [C] extern и связывание
От: DirtyGarry  
Дата: 09.10.14 10:18
Оценка:
Здравствуйте, Kernan.

Буду признателен, если Вы поясните мне цитату, которая приведена ниже.

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:

extern int i;
   // static storage duration
   // file scope
   // ? linkage

void f(void)
{
    extern int j;
        // static storage duration
        // block scope
        // ? linkage
}

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.

Re[2]: [C] extern и связывание
От: DirtyGarry  
Дата: 09.10.14 10:20
Оценка:
Здравствуйте, uzhas, Вы писали:

U>почему вы решили, что это не так?


Буду признателен, если Вы прокомментируете мой ответ Kernan. Спасибо.
Re[2]: [C] extern и связывание
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 09.10.14 10:32
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>И вот чего минусуют? Вопрос то интересный.

Потому что это разжёвано в книгах. Просто надо внимательно почитать и выяснить значения непонятных терминов вроде области видимости, жизни, единицы трансляции, компоновки, ODR, объявления и определения. Это всё описано в Ритчи.
Sic luceat lux!
Re[3]: [C] extern и связывание
От: koenjihyakkei Россия  
Дата: 09.10.14 11:03
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Потому что это разжёвано в книгах. Просто надо внимательно почитать и выяснить значения непонятных терминов вроде области видимости, жизни, единицы трансляции, компоновки, ODR, объявления и определения. Это всё описано в Ритчи.


Где конкретно там это разжевано? Именно данный случай конфликта двух этих классов памяти в одном файле? Я открывал книгу, пробежался поиском, никакого разжевывания не увидел. Плюс почему в 2008 студии код прошел? Понятно, что мелокософты на сишный компилер давно забили, но С89 он вроде как полностью поддерживает, а книга Ритчи как раз о нем..
Re[3]: [C] extern и связывание
От: uzhas Ниоткуда  
Дата: 09.10.14 11:28
Оценка:
Здравствуйте, DirtyGarry, Вы писали:

DG>Буду признателен, если Вы прокомментируете мой ответ Kernan. Спасибо.


да, я был не прав, там все намного сложнее
вот что нагуглилось : http://stackoverflow.com/questions/17041571/static-declaration-of-m-follows-non-static-declaration
если коротко, то в C11 extern может сохранять linkage, только если он уже объявлен выше
Re[5]: [C] extern и связывание
От: DirtyGarry  
Дата: 09.10.14 12:07
Оценка:
Здравствуйте, uzhas, Вы писали:

U>>если коротко, то в C11 extern может сохранять linkage, только если он уже объявлен выше


U>1.

U>

U>If the variable was declared static earlier in the file (outside of any function definition), then it has internal linkage.


Спасибо, этот момент я упустил А какой смысл в этом extern если переменная была определена выше?
Re: [C] extern и связывание
От: B0FEE664  
Дата: 09.10.14 13:06
Оценка:
Здравствуйте, 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 — внутреннее.
И каждый день — без права на ошибку...
Отредактировано 09.10.2014 13:07 B0FEE664 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.