статическая переменная в c
Привет, я готовлюсь к тесту на C, и я столкнулся с вопросом, на который я не могу найти ответа.
Программист написал программу для подсчета количества пользователей (Count.h, Count.c):
И тестер для проверки:
На удивление результат был:
Я не понимаю, почему при таком использовании статической переменной счетчик не увеличивается .. почему они получили такой ввод?
Спасибо вам всем!
7 ответов
Подумайте об этом как о том, что «файлов .h не существует». Что происходит, так это то, что файлы .h включаются в файлы .c, и только файлы .c компилируются (и связываются (смешиваются) вместе).
В вашем случае у вас есть 2 файла .c с
Каждый counter специфичен для того файла .c, в котором он находится. counter в CounterMain.c — это переменная, отличная от counter в Counter.c.
У вас должно быть одно одно определение счетчика. У вас может быть несколько объявлений (обычно в файлах .h)
Оххххххххххххххххх и вот что такое static . Не используйте его в глобальном масштабе!
В C областью статической переменной является исходный файл, в котором она определена.
Поскольку вы загружаете этот заголовок в 2 отдельных файла .c, каждый файл получает уникальную переменную. Увеличение «счетчика» в одном файле не влияет на «статическую» переменную в другом файле.
Подробнее см. в этом описании. Чтобы переменная была видимой и совместно используемой в нескольких файлах, ее необходимо объявить как extern. Иначе:
Статические глобальные переменные: переменные, объявленные как статические на верхнем уровне исходного файла (вне каких-либо определений функций), видны во всем этом файле («область файла»).
static int counter = 0;
Если переменная была определена с использованием спецификатора статического класса хранения, переменная имеет внутренняя связь . Это означает, что вы можете использовать counter внутри той же единицы перевода, в которой это определено.
Программа на C создается путем объединения одной или нескольких единиц перевода вместе в программу.
Единица перевода — это, по сути, предварительно обработанный исходный файл. Он содержит все включенные заголовочные и исходные файлы, указанные в директивах #include , и исключает все, что исключено #if или подобными директивами.
Когда переменная в области видимости файла объявляется static , она дает имя переменной внутренняя связь . Это означает, что имя относится к объекту, локальному для единицы перевода, в которой оно появляется. Если имя используется в другой единице перевода, тогда оно не может относиться к объекту в этой единице перевода, оно должно относиться к другому объекту.
[Напротив, имя с внешней связью относится к одному и тому же объекту независимо от единицы перевода, в которой используется это имя.]
Когда вы помещаете такое объявление в файл заголовка, это означает, что каждая единица перевода, которая включает файл заголовка, имеет свой собственный уникальный объект с именем counter , который отличается от любого объекта с именем counter в любом другом единица перевода.
В вашем случае есть один counter в блоке перевода, созданном из CounterMain.c , и отдельный в блоке перевода, созданном из Count.c . Один в Count.c никогда не увеличивается, но возвращается getUserNum() , один в CounterMain.c увеличивается в main , но больше нигде не используется.
Ключевое слово static означает, что при использовании для определения функций или глобальных переменных функция или переменная должны иметь internal linkage , то есть они не должны отображаться как глобальный символ. Следовательно, каждая единица компиляции, включая Counter.h , будет иметь свою собственную локальную копию counter , которая не будет конфликтовать с другими.
В этом случае Counter.c и CounterMain.c имеют разные переменные count , что и приводит к тому, что вы описали.
Решение состоит в том, чтобы изменить определение counter в Counter.h на объявление:
extern int counter;
и поместить определение в Counter.c :
int counter = 0;
После этого CounterMain и любые другие единицы компиляции, включая Counter.h , должны иметь доступ к единственному экземпляру counter , но вы можете захотеть заняться information hiding и получить доступ к нему только через функции в Counter , в результате получается более чистый interface .
Это потому, что статическая переменная объявлена в заголовке. В C статические переменные существуют только в файле .c , в котором они объявлены. Поскольку ваш .h включен (директивы #include можно рассматривать как не что иное, как операцию копирования и вставки) в двух разных файлах .c, создаются две статические переменные с именем counter , по одной в каждом файле. Ваш тестовый файл увеличивает свою локальную переменную counter , но переменная, возвращаемая getUsersNum , получена из другого файла C и полностью независима.
Вопрос пытается получить доступ к статической переменной из файла, отличного от того, в котором она была объявлена. Вы должны знать, что это (напрямую) невозможно. Чтобы увеличить правый счетчик, вам понадобится функция, которая работает с переменной counter Counter.c .
Переменная static доступна только в том файле, в котором она определена. В этом примере и Counter.c , и CounterMain.c имеют свою собственную переменную counter .
Когда выполняется ++counter , это обновляет переменную, объявленную в CounterMain.c . Но когда вызывается getUsersNum() , он возвращает значение переменной counter из Counter.c , которое не было увеличено.
Если вы измените getUsersNum() на counter , вы увидите, что переменная counter , объявленная в CounterMain.c , была увеличена.