Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.74/172: Рейтинг темы: голосов - 172, средняя оценка - 4.74
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
1

Ключевое слово static для переменных в файле

18.10.2016, 22:37. Показов 32051. Ответов 24
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Много где пишут, если в файле объявить переменную с классом памяти static, то такая переменная будет видна только в том файле где она объявлена. Но на практике так не происходит. Чего я не понимаю?

файл 1
C
1
2
3
4
5
6
7
8
#include <stdio.h>
#include "static.c"
 
int main()
{
    printf("%d", v);
    return 0;
}
файл 2(static.c)
C
1
static int v = 54000;
В файле 1 выводится значение статичной переменной v.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.10.2016, 22:37
Ответы с готовыми решениями:

Считать из первого файла ключевое слово и цвет и выделить слово во втором файле
считать из 1 файла ключевое слово и цвет и выделить слово во 2ом файле. файлы html. #include...

Подсчитать сколько раз появляется каждое ключевое слово языка С в символьном файле с программой на С
Всем привет! Помогите Подсчитать сколько раз появляется каждое ключевое слово языка С в ...

Что означает ключевое слово const?
Что означает ключевое слово const?

Ключевое слово static
Здорова господа!!! Есть две функции f1() и f2(). #include &lt;iostream&gt; using std::cout; using...

24
81 / 81 / 33
Регистрация: 03.03.2013
Сообщений: 311
18.10.2016, 23:05 2
sys_beginner, на стадии компиляции должен подключаться файл с объявленной переменной ты не правильно понял

Добавлено через 11 минут
Цитата Сообщение от Novi4ekC Посмотреть сообщение
sys_beginner, на стадии компиляции должен подключаться файл с объявленной переменной ты не правильно понял
пардон, то я не так понял

Добавлено через 1 минуту
sys_beginner, попробуй тоже объявить переменную v в первом файле в вывести значение
0
Диссидент
Эксперт C
27706 / 17322 / 3812
Регистрация: 24.12.2010
Сообщений: 38,979
18.10.2016, 23:09 3
sys_beginner, То, что ты написал, абсолютно эквивалентно
C
1
2
3
4
5
6
7
8
#include <stdio.h>
static int v =54000;
 
int main()
{
    printf("%d", v);
    return 0;
}
И все совершенно совпадает с
Цитата Сообщение от sys_beginner Посмотреть сообщение
такая переменная будет видна только в том файле где она объявлена.
Если ты подключишь #include "static.c" к другому исходнику, v будет виден и там. Но только это будут совершенно разные переменные, занимающие разные области памяти.
Все-таки у меня большое подозрение, что ты возлагаешь на #include какие-то надежды, которые она не оправдывает
1
81 / 81 / 33
Регистрация: 03.03.2013
Сообщений: 311
18.10.2016, 23:09 4
sys_beginner, Статическая переменная
0
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
18.10.2016, 23:10  [ТС] 5
Цитата Сообщение от Novi4ekC Посмотреть сообщение
попробуй тоже объявить переменную v в первом файле в вывести значение
Ошибку получаю. Redefenition
0
81 / 81 / 33
Регистрация: 03.03.2013
Сообщений: 311
18.10.2016, 23:15 6
Цитата Сообщение от sys_beginner Посмотреть сообщение
Ошибку получаю. Redefenition
значит она уже об'явлена в подключенном файле

Добавлено через 2 минуты
Вспомни, что инклуд просто вставляет содержимое файла в место вызова макрокоманды
0
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
18.10.2016, 23:15  [ТС] 7
Цитата Сообщение от Байт Посмотреть сообщение
Если ты подключишь #include "static.c" к другому исходнику, v будет виден и там.
Это я понимаю. Но как объяснить утверждение что static переменные видны только в файле в котором они определены?
Ведь переменные которые находятся в файлах которые не включены друг в друга и так не видны

Цитата Сообщение от Novi4ekC Посмотреть сообщение
значит она уже об'явлена в подключенном файле
Ну да
0
81 / 81 / 33
Регистрация: 03.03.2013
Сообщений: 311
18.10.2016, 23:20 8
Цитата Сообщение от sys_beginner Посмотреть сообщение
Ведь переменные которые находятся в файлах которые не включены друг в друга и так не видны
этот классификатор используется при создании проектов.
0
Диссидент
Эксперт C
27706 / 17322 / 3812
Регистрация: 24.12.2010
Сообщений: 38,979
18.10.2016, 23:29 9
Цитата Сообщение от sys_beginner Посмотреть сообщение
Это я понимаю. Но как объяснить утверждение что static переменные видны только в файле в котором они определены? Ведь переменные которые находятся в файлах которые не включены друг в друга и так не видны
А! Понял тебя. Экий ты придира!
static int v, объявленный в main.c НЕ ВИДЕН в файле over.c. Сколько и где ни пиши в последнем static int v, или даже extern int v, тот, майновский, будет не виден. Это будет совсем другая переменная.

Добавлено через 2 минуты
И совершенно неважно, подключишь ты его #includ-ом или напишешь живьем.
ЗЫ. Си очень простой язык.
2
81 / 81 / 33
Регистрация: 03.03.2013
Сообщений: 311
18.10.2016, 23:33 10
Цитата Сообщение от Байт Посмотреть сообщение
ЗЫ. Си очень простой язык.
не проще ассемблера
0
Диссидент
Эксперт C
27706 / 17322 / 3812
Регистрация: 24.12.2010
Сообщений: 38,979
18.10.2016, 23:35 11
Цитата Сообщение от sys_beginner Посмотреть сообщение
переменные которые находятся в файлах которые не включены друг в друга и так не видны
Если они описаны как extern, то очень даже видны. Вот, все функции по умолчанию - extern, и видны, лапушки, видны ото всюду!
Правда, злоупотреблять экстернами умные люди не советуют, но это уж как себя поставишь...
2
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
18.10.2016, 23:45  [ТС] 12
Байт,
Спасибо что пытался донести суть)) Но "дуб" во мне не засыпает. Всё никак не пойму.
Поищу потом ещё материалы. Почитаю снова про классы памяти
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
19.10.2016, 00:41 13
Как и многое другое в C, static - перегружен. Этот keyword может использоваться и для указания класса памяти (static vs automatic), и для указания области видимости (global vs local).

Автоматические переменные "живут" на стеке и их время жизни ограничено вызовом функции, а область видимости - телом функции. Статические переменные размещаются в сегменте данных и существуют все время исполнения программы, а их область видимости - от объявления до конца единицы трансляции.

Обычно, атрибут static используется, если переменная должна быть в единственном экземпляре и разделяться несколькими функциями. Размещение в сегменте данных делает ее независимой от вызова функции и позволяет нескольким функциям, вызываемым в различные моменты, обмениваться данными между собой (подобно тому, как шпионы используют дупло для передачи донесений).

Не по теме:

Аналогичный механизм использует OS - объекты ядра (file, mutex etc) "статичны" по отношению к программам пользователя и позволяют им взаимодействовать между собой.


Часто функции объявляют как static, чтобы перекрыть дефолтную видимость (external) и сделать недоступными за пределами модуля. В частности, в разных единицах трансляции можно иметь различные функции с тем же самым именем.

Static: Многоцелевое ключевое слово
2
Вездепух
Эксперт CЭксперт С++
11694 / 6373 / 1724
Регистрация: 18.10.2014
Сообщений: 16,066
19.10.2016, 00:45 14
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Цитата Сообщение от sys_beginner Посмотреть сообщение
то такая переменная будет видна только в том файле где она объявлена.
Не в файле, а в единице трансляции. Единицей трансляции называется уже обработанный препроцессором исходный файл, т.е. файл с уже полностью подставленными в него всеми #include-файлами, полностью подставленным макросами и т.п.

В исходном примере единица трансляции будет выглядеть примерно так

C
1
2
3
4
5
6
7
8
9
10
11
/* 
  Подставленое сюда все содержимое stdio.h 
*/
 
static int v = 54000;
 
int main()
{
    printf("%d", v);
    return 0;
}
Вот в этой единственной единице трансляции и видна переменная v, как и обещали.
1
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
19.10.2016, 10:22  [ТС] 15
gazlan,
Спасибо. Я читал информацию по той ссылке. Там именно написано файл, а не единица трансляции. В этом и была загвоздка.
Только код внутри того же файла может увидеть переменную (её область видимости ограничена файлом).
Хоть единица трансляции это тоже файл, но о том что конкретно имеется ввиду не имея опыта остается только догадываться...

TheCalligrapher,
C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <one.c>
#include <two.c>
#include <three.c>
 
int main()
{
    return 0;
}
one + stdio = 1 единица трансляции
two + one + stdio = 1 единица трансляции
three + two + one + stdio = 1 единица трансляции

Я правильно понимаю? Если так, то учитывая, что файлы one и two попадают в разные единицы трансляции которые компилируются отдельно, это приводит к дублированию исходного кода.
Исходный код ведь в память загружается в момент запуска программы? Выходит, такая ситуация приводит к оверхеду. Как с этим бороться?

Добавлено через 10 минут
Как вариант использовать условную компиляцию, может есть другие, более правильные способы?
C
1
2
3
4
#ifndef SOMETHING
#define SOMETHING
code...
#endif
Добавлено через 23 минуты
Но в таком случае интересно, как получить доступ к уже скомпилированному коду который не будет включен через include за счет условной компиляции. только через extern?
Как в таких ситуациях поступать? Хочется знать как обычно делают опытные разработчики
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
19.10.2016, 17:27 16
Следует учитывать, что до компиляции работает препроцессор (в ранних версиях компиляторов это была отдельная программа). В частности, он обрабатывает все директивы #include, превращая дерево включений в единицу трансляции.

Но, от того, что вы N раз напишете
C++
1
2
3
4
#include <foo.h>
#include <foo.h>
...
#include <foo.h>
оно НЕ появится N раз в таблицах транслятора: тождественные определения будут учтены как одно, различные приведут к выдаче сообщения о переопределении. Оверхед связан только с временем компиляции/размером промежуточных файлов.

IMHO, стоит избегать "каскадного" включения заголовочных файлов (одного в другой) - это приводит к тяжелым рекурсивным зависимостям. Иными словами, я предпочитаю в каждом C/C++ файле иметь список только реально необходимых в нем H-файлов.

Модификатор extern обычно, появляется либо как следствие продуманной оптимизации, либо как результат неверного дизайна. Для межмодульного азаимодействия есть функции, общие переменные часто ведут к тяжелым труднообнаруживаемым ошибкам.
1
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
19.10.2016, 17:47  [ТС] 17
Цитата Сообщение от gazlan Посмотреть сообщение
Иными словами, я предпочитаю в каждом C/C++ файле иметь список только реально необходимых в нем H-файлов.
А реализацию .h файла включаете в сам .h файл с помощью #include?
Цитата Сообщение от gazlan Посмотреть сообщение
Модификатор extern обычно, появляется либо как следствие продуманной оптимизации, либо как результат неверного дизайна
А где можно узнать как делать правильно? Желательно с обноснованием точки зрения

Цитата Сообщение от gazlan Посмотреть сообщение
Оверхед связан только с временем компиляции/размером промежуточных файлов.
То есть если 2 единицы трансляции используют один и тот же файл, в конечном счете дубликат кода удаляется и используется один экземпляр?

Раз уж мы заговорили о правильности. То как быть в случаях, когда нужна функция printf, но из за одной функции приходится подключать весь stdio. Как избавиться от лишних функций?
0
Диссидент
Эксперт C
27706 / 17322 / 3812
Регистрация: 24.12.2010
Сообщений: 38,979
19.10.2016, 17:57 18
gazlan, sys_beginner, имхо, вы куда-то совсем не в ту степь закатились
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
19.10.2016, 18:14 19
Цитата Сообщение от sys_beginner Посмотреть сообщение
А реализацию .h файла включаете в сам .h файл с помощью #include?
Не понял вопроса. В H-файле размещаются описания, кода в них нет. Реализация выносится в C/C++. Это позволяет разделить интерфейс и реализацию. Тому кто использует функцию важно знать детали контракта (количество и типы параметров, тип возвращаемого значения), но не детали реализации (более того, они должны быть преднамеренно скрыты).

А где можно узнать как делать правильно? Желательно с обноснованием точки зрения
Правильно - extern никогда не должен появляться :-) Но если вы понимаете, что делаете, то можете себе позволить правило нарушить - на ваш собственный риск.


То есть если 2 единицы трансляции используют один и тот же файл, в конечном счете дубликат кода удаляется и используется один экземпляр?
Он НЕ появляется. Транслятор читает исходный код и строит свои собственные внутренние таблицы (которые потом превращаются в объектный код). В них нет дубликатов.

как быть в случаях, когда нужна функция printf, но из за одной функции приходится подключать весь stdio. Как избавиться от лишних функций?
Это забота линкера (обычно, последняя фаза трансляции). При связывании объектного кода, "хороший" линкер выбрасывает units, на которые нет ссылок.
1
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
19.10.2016, 18:45  [ТС] 20
gazlan,
Спасибо, вы очень помогли!
Только не понятно одно
Цитата Сообщение от gazlan Посмотреть сообщение
В H-файле размещаются описания, кода в них нет. Реализация выносится в C/C++.
Выглядит привлекательно. Но откуда компилятор узнает про .с файл(реализацию интерфейса) если его не включать в код программы явно?
Допустим нахожусь в директории где расположены файлы программы. Компилятор запускаю из командной строки с помощью вызова сс указав один или несколько файлов для компиляции(есть ли команда что бы компилировался весь код из директории рекурсивно?). Или через Visual Studio

Добавлено через 30 секунд
Байт,
Не
0
19.10.2016, 18:45
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.10.2016, 18:45
Помогаю со студенческими работами здесь

Зачем использовать ключевое слово static?
Здравствуйте. Зачем использовать ключевое слово static? И в каких ситуациях нужно использовать...

Ключевое слово static в объявлении функции
Доброго времени суток. У меня возник вопрос по поводу использования слово static в объявлении...

Зачем и когда нужно писать ключевое слово static
Не как не могу понять зачем и когда нужно писать ключевое слово static. Может вы мне подскажите ?

Классы.Ключевое слово static - выдает ошибку "неразрешенный внешний символ"
Всем доброго времени суток. Изучаю С++ по Шпаку и по урокам на сайте cppstudio.com, предварительно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru