Простой вопрос про static
, найти ответ не могу в книгах
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.140] |
|
|
Простой вопрос про static
, найти ответ не могу в книгах
|
Сообщ.
#1
,
|
|
|
|
Привет всем!
У меня тут вопрос вроде бы простой возник : Чем отличаются статические(static) глобальные переменные от простых глобальных переменных. |
|
Сообщ.
#2
,
|
|
|
|
Тем же, чем статические функции (не методы класса) отличаются от просто функций - они имеют internal linkage.
Т.е. в разных модулях могут быть переменные с одинаковым именем. Для нестатических переменных такое не прокатит. |
|
Сообщ.
#3
,
|
|
|
|
Если объявляешь переменную вне функции без квалификаторов, то переменная поумолчанию делается статической.
Добавлено Цитата Hryak @ Т.е. в разных модулях могут быть переменные с одинаковым именем. Для нестатических переменных такое не прокатит. Что-то я не сталкивался с таким. Интересно, а если в третьем модуле будет extern ссылка на переменную которая содержится одновременно в двух других модулях, то из какого модуля она залинкуется? Добавлено Я замечал только одно отличие - если объявить переменную со словом static и не использовать её, то компилятор выдаёт предупреждение "not referenced". |
|
Сообщ.
#4
,
|
|
|
|
ну так столкнись
проверь - минутное дело |
|
Сообщ.
#5
,
|
|
|
|
Объявляя глобальную переменную статической ее нельзя будет вызвать извне данного модуля.
|
|
Сообщ.
#6
,
|
|
|
|
Цитата GreenGen @ Привет всем! У меня тут вопрос вроде бы простой возник : Чем отличаются статические(static) глобальные переменные от простых глобальных переменных. Статические переменные Статические переменные, в отличие от глобальных, неизвестны вне своей функции или файла, и сохраняют свои значения между вызовами. Это очень полезней создании обобщенных функции и библиотек функций, которые могут использовать другими программистами. Статические переменные отличаются как от локальных, так и от глобальных переменных. Локальные статические переменные Если локальная переменная объявлена с помощью спецификатора static, компилятор выделит для нее постоянное место хранения, как и для глобальной переменной Принципиальное отличие локальной статической переменной от глобальной состоит в том, что первая остается доступной лишь внутри своего блока. Проще говоря, локальная статическая переменная — это локальная переменная, сохраняющая свои значения между вызовами функции. Такие переменные очень полезны при создании изолированных функций, поскольку между вызовами их можно использовать в других частях программы. Если бы статических переменных не было, пришлось бы применять глобальные переменные, порождая неизбежные побочные эффекты. Примером удачного применения статических переменных является генератор чисел, который порождает новое число, используя предыдущее значение. Для хранения этого числа можно было бы использовать глобальную переменную, однако при каждом новом вызове ее пришлось бы объявлять заново, постоянно проверяя, не конфликтует ли она с другими глобальными переменными. Применение статической переменной легко решает эту проблему. ![]() ![]() int series(void) { static int series_num; series_num = series_num+23; return series_num; } В этом примере переменная series_num продолжает существовать между вызовами функции, а локальная переменная каждый раз создавалась бы при входе и уничтожалась при выходе из функции. Таким образом, каждый вызов функции series () порождает новый элемент ряда, используя предыдущее значение и не прибегая к глобальной переменной. Локальную статическую переменную можно инициализировать. Начальное значе¬ние присваивается лишь один раз, а не при каждом входе в блок, как это происходит с локальными переменными. Например, в приведенной ниже версии функции se¬ries () переменная eeries_num инициализируется числом 100. ![]() ![]() int series(void) { static int series_nuiti = 100; series_num = series_num+23; return series_num; } Теперь ряд будет всегда начинаться с числа 123. Хотя во многих приложениях это вполне приемлемо, обычно генераторы чисел предоставляют пользователю право выбора начального значения. Для этого можно сделать переменную series_num глобальной. Однако именно для того, чтобы избежать этого, и были созданы статические переменные. Это приводит ко второму способу использования статических переменных. Глобальные статические переменные Применение спецификатора static к глобальной переменной заставляет компилятор создать глобальную переменную, видимую только в пределах текущего файла. Несмотря на то что эта переменная остается глобальной, в других файлах она не существует. Следовательно, изменить ее значение путем вмешательства извне невозможно. Это предотвращает побочные эффекты. В некоторых ситуациях, в которых локальные статические переменные оказываются недостаточными, можно создать небольшой файл, содержащий лишь функции, которые используют конкретную глобальную статическую переменную, отдельно скомпилировать его и применять без риска возникновения побочных эффектов. Чтобы проиллюстрировать применение глобальной статической переменной, перепишем генератор чисел из предыдущего раздела таким образом, чтобы начальное значение задавалось при вызове функции series_start(). Весь файл, содержащий функции eeriest), series_start () и series_num(), показан ниже. ![]() ![]() /* Все функции должны находиться в одном и том же файле. */ static int series_num; void series_start(int seed); int series(void); int series(void) { series_num = series_num+23 ; return series_num; } /* Инициализация переменной series_num */ void series_start(int seed) { series_num = seed; } Вызов функции series_start() инициализирует генератор чисел. После этого следующий элемент ряда порождается новым вызовом функции seriesO. К сведению: локальные статические переменные видимы лишь в пределах блока, где они объявлены, а глобальные статические переменные — в пределах файла. Если поместить функции series() и series() и start() в библиотеку, то переменная series_num станет невидимой. Более того, в программе можно объявить новую переменную series_num (разумеется, в другом файле). По существу модификатор static позволяет создавать переменные, видимые лишь в пределах функций не порождая побочных эффектов. Модификатор static позволяет скрывать часть программы от других модулей Это чрезвычайно важно при разработке больших и сложных программ. ![]() ![]() 2 GreenGen, надеюсь я заслужил + :lol: |
|
Сообщ.
#7
,
|
|
|
|
Цитата polyglott @ Если объявляешь переменную вне функции без квалификаторов, то переменная поумолчанию делается статической. Без каких квалификаторов? А как её сделать нестатической тогда? Написать nostatic int g;, что ли? Цитата Интересно, а если в третьем модуле будет extern ссылка на переменную которая содержится одновременно в двух других модулях, то из какого модуля она залинкуется? Ни из какого. Линковка не пройдет. |
|
Сообщ.
#8
,
|
|
|
|
Цитата Hryak @ А как её сделать нестатической тогда? Написать nostatic int g;, что ли? Да, я ступил. Цитата Hryak @ Без каких квалификаторов Ну там всякие квалификаторы-шмалификаторы, типа const, static, auto, extern... |
|
Сообщ.
#9
,
|
|
|
|
Цитата polyglott @ Ну там всякие квалификаторы-шмалификаторы, типа const, static, auto, extern... Понятно. Но квалификаторами являются только const и volatile. Остальное - спецификаторы. |
|
Сообщ.
#10
,
|
|
|
|
Вобщем как я понял если просто глобальная переменная то её область видимости 1 фаил в котором она объявлена а static глобальная переменная её видно во всех файлах проекта.
Как я понял они различаются областью видимости? |
|
Сообщ.
#11
,
|
|
|
|
Цитата GreenGen @ Вобщем как я понял если просто глобальная переменная то её область видимости 1 фаил в котором она объявлена а static глобальная переменная её видно во всех файлах проекта. Нет, конечно же.Пора на покой. |
|
Сообщ.
#12
,
|
|
|
|
Цитата GreenGen @ Вобщем как я понял если просто глобальная переменная то её область видимости 1 фаил в котором она объявлена а static глобальная переменная её видно во всех файлах проекта. Наоборот. static глобальная переменная видна только в том файле, в котором объявлена, просто глобальная --- во всех. |
|
Сообщ.
#13
,
|
|
|
|
GreenGen вообщем прочитай в книге про internal linkage (атрибут статик) и external linkage, и как проходит процесс компиляции и компоновки.
|
|
Сообщ.
#14
,
|
|
|
|
Цитата Hryak @ Так нельзя! Это безграмотно! Надо писать nonstatic. Написать nostatic int g;, что ли? |
|
Сообщ.
#15
,
|
|
|
|
Цитата Hryak @ А как её сделать нестатической тогда? Написать nostatic int g;, что ли? по умолчанию функции итак имеют не статик спецификатор, а именно extern Цитата Adil @ Так нельзя! Это безграмотно! Надо писать nonstatic. тоесть грамотно ,надо писать extern или ничего. |
|
Сообщ.
#16
,
|
|
|
|
Цитата Sazabis @ Не могут они иметь extern, поскольку extern используется только в объявлениях (declaration), а фунция (не прототип, а именно функция) - это определение (definition). по умолчанию функции итак имеют не статик спецификатор, а именно extern |
|
Сообщ.
#17
,
|
|
|
|
Цитата -Daemon- @ Не могут они иметь extern, поскольку extern используется только в объявлениях (declaration), а фунция (не прототип, а именно функция) - это определение (definition). и ? что, функция не может быть external linkage ? |
|
Сообщ.
#18
,
|
|
|
|
Sazabis объявление, но не определение
Добавлено Возможно я не правильно понял твою реплику. |
|
Сообщ.
#19
,
|
|
|
|
Цитата Adil @ Цитата Hryak @ Так нельзя! Это безграмотно! Надо писать nonstatic.Написать nostatic int g;, что ли? -Added Цитата Sazabis @ Цитата Hryak @ А как её сделать нестатической тогда? Написать nostatic int g;, что ли? по умолчанию функции итак имеют не статик спецификатор, а именно extern Зачем слова из контекста вырываешь? Перечитай сквотированное мной перед этими словами. |
|
Сообщ.
#20
,
|
|
|
|
Цитата Hryak @ Зачем слова из контекста вырываешь? Перечитай сквотированное мной перед этими словами. значит не понял, и опять перечитал не понял )) Вопрос какой нибуть был вообще ? Цитата Hryak @ Написать nostatic int g;, что ли? написать extern int g; extern это проивоположность static. |
|
Сообщ.
#21
,
|
|
|
|
Цитата Sazabis @ Цитата Hryak @ Зачем слова из контекста вырываешь? Перечитай сквотированное мной перед этими словами. значит не понял, и опять перечитал не понял )) Вопрос какой нибуть был вообще ? Повторяю содержание первой части поста #7: <<<<<<<<<< Цитата polyglott @ Если объявляешь переменную вне функции без квалификаторов, то переменная поумолчанию делается статической. Без каких квалификаторов? А как её сделать нестатической тогда? Написать nostatic int g;, что ли? >>>>>>>>>> Во-первых, речь шла про переменные, а не функции. Во-вторых, extern вообще не при делах, т.к. определение не может содержать extern, про что тут уже говорили. В-третьих, я знаю, что функции по умолчанию имеют внешнюю линковку . |
|
Сообщ.
#22
,
|
|
|
|
Цитата Hryak @ определение не может содержать extern, про что тут уже говорили. |
|
Сообщ.
#23
,
|
|
|
|
Цитата LPBOY @ Цитата Hryak @ определение не может содержать extern, про что тут уже говорили. ![]() Цитата A declaration is a definition unless it declares a function without specifying the function's body (dcl.fct.def), it contains the extern specifier (dcl.stc) or a linkage-specification* |
|
Сообщ.
#24
,
|
|
|
|
Цитатка не до конца. Цитата A declaration is a definition unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a function-body, ![]() ![]() extern int x = 1; // определение, компилится нормально extern int fn() // определение, компилится нормально { return 1; } |
|
Сообщ.
#25
,
|
|
|
|
Уболтали.
|
|
Сообщ.
#26
,
|
|
|
|
Цитата LPBOY @ extern int fn() // определение, компилится нормально Век живи, век учись... |
|
Сообщ.
#27
,
|
|
|
|
Цитата Hryak @ А как её сделать нестатической тогда? Написать nostatic int g;, что ли? >>>>>>>>>> Подумай! Как глобальная переменная может быть нестатической? Все глобальные переменные - статические. По отношению к глобальным переменным слово static приобретает просто иной смысл, чем по отношению к локальным |
|
Сообщ.
#28
,
|
|
|
|
Цитата gryz @ По отношению к глобальным переменным слово static приобретает просто иной смысл, чем по отношению к локальным Спасибо за просвещение, не знал этого. |
|
Сообщ.
#29
,
|
|
|
|
gryz тогда встречный вопрос по поводу линковки. Почему если в хедер файле объявить переменную и инклудить ее в две разные единицы трансляции - возникает ошибка линковщика. Если же прописать спецификатор static, т.е. явно указать способ линковки, - то ествественно ошибка исчезает.
|
|
Сообщ.
#30
,
|
|
|
|
Цитата -Daemon- @ gryz тогда встречный вопрос по поводу линковки. Почему если в хедер файле объявить переменную и инклудить ее в две разные единицы трансляции - возникает ошибка линковщика. Если же прописать спецификатор static, т.е. явно указать способ линковки, - то ествественно ошибка исчезает. Этот static никаким образом не относится к статику для локальных переменных и членов классов. static для глобальных переменных как раз и делает их уникальными для каждой единицы трансляции. Фактически в этом случае компилятор создает несколько независимых глобальных переменных по одной для каждой единицы трансляции |
|
Сообщ.
#31
,
|
|
|
|
gryz я это все понимаю. Но ты вот написал выше:
Цитата Если все глобальные переменные - статические (в глобальной области видимости), значит по идее они имеют internal linkage. Тогда почему пример, который я приводил выше, без ключевого слова static, приводит к ошибке линковщика? Как глобальная переменная может быть нестатической? Все глобальные переменные - статические. |
|
Сообщ.
#32
,
|
|
|
|
-Daemon-
Тут надо смотреть на то, как ты понимаешь понятие "статическая переменная". ![]() --- When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared). ---- и --- Objects and variables defined outside all blocks have static lifetime and external linkage by default. A global object or variable that is explicitly declared as static has internal linkage. --- говоря, что переменная статическая. Я не имею ввиду, что у нее internal linkage, а имею ввиду ее "статическое" поведение |
|
Сообщ.
#33
,
|
|
|
|
-Daemon-, ну понятно же, что просто путаница в терминологии: "статический" по отношению к времени жизни и к области видимости. Хотя gryz неприминул попытаться Hryak'а на этом подловить.
|
|
Сообщ.
#34
,
|
|
|
|
gryz ок.
Adil я сам запутался |
|
Сообщ.
#35
,
|
|
|
|
Цитата Adil @ -Daemon-, ну понятно же, что просто путаница в терминологии: "статический" по отношению к времени жизни и к области видимости. Хотя gryz неприминул попытаться Hryak'а на этом подловить. Все таки, у меня в процессе работы с с++ сложилось мнение, что статическая переменная - это скорее переменная, имеющая характерное время жизни, чем характерную область видимости. Добавлено Меня огорчило как на polyglott набросились |
|
Сообщ.
#36
,
|
|
|
|
Цитата gryz @ статическая переменная - это скорее переменная, имеющая характерное время жизни, чем характерную область видимости. Скорее - это завист от контекста употребления. Добавлено Цитата Adil @ , хм, а меня - порадовало, что не на меня так набросились. Будь оптимистом. Меня огорчило как на polyglott набросились |
|
Сообщ.
#37
,
|
|
|
|
Цитата Adil @ хм, а меня - порадовало, что не на меня так набросились. Будь оптимистом. ![]() Ну на тебя то за то? nonstatic - неплохое ключевое слово. можно было бы и попользоваться им )) |
|
Сообщ.
#38
,
|
|
|
|
Цитата Adil @ -Daemon-, ну понятно же, что просто путаница в терминологии: "статический" по отношению к времени жизни и к области видимости. Хотя gryz неприминул попытаться Hryak'а на этом подловить. "Попытка - не пытка" © ЛПБ Цитата gryz Все таки, у меня в процессе работы с с++ сложилось мнение, что статическая переменная - это скорее переменная, имеющая характерное время жизни, чем характерную область видимости. Так это твое мнение. Моё мнение - "Статическая переменная - это переменная объявленная с использованием ключевого слова static". Сомневаюсь, что мое определение хуже твоего, потому что оно универсальней. Просто смысл зависит от контекста (кстати, перечитай ветку и найди хоть одно упоминание того, что речь шла про твой контекст - т.е. про локальные переменные) Я не применяю такое определение, когда контест неясен - в этом случае всегда добавляю к выражению "глобальная"/"локальная". А то, что ты называешь "статической переменной", называю "переменной со статическим временем жизни", если речь идет именно про время жизни. |