Эта путаница обычно возникает из-за того, что ключевое слово static
выполняет две цели.
При использовании на уровне файлов, он контролирует видимость своего объекта за пределами единицы компиляции, а не длительности объекта (видимость и продолжительность неспециалист условия, которые я использую во время учебных занятий, стандарт ISO использует разные термины, которые вы, возможно, захотите узнать в конце концов, но я обнаружил, что они путают большинство начинающих студентов).
Объекты, созданные на уровне файлов, уже имеют свою продолжительность в силу того факта, что они находятся на уровне файлов. Ключевое слово static
просто делает их невидимыми для компоновщика.
При использовании внутри функций он контролирует продолжительность, а не видимость. Видимость уже решена, поскольку она находится внутри функции - ее нельзя увидеть вне функции. В этом случае ключевое слово static
вызывает создание объекта одновременно с объектами уровня файла.
Обратите внимание, что технически статический уровень функции не обязательно возникает до тех пор, пока функция не будет сначала вызвана (и это может иметь смысл для C++ с ее конструкторами), но каждая реализация C, которую я когда-либо использовал, создает свой уровень функции статики одновременно с объектами уровня файла.
Кроме того, пока я использую слово «объект», я не имею в виду это в смысле объектов C++ (так как это вопрос C). Просто потому, что static
может применяться к переменным или функциям на уровне файлов, и для этого мне нужно всеохватывающее слово.
Статичность уровня функции по-прежнему используется довольно много - они могут вызвать проблемы в многопоточных программах, если это не обслуживается, но при условии, что вы знаете, что делаете (или вы не нарезаете резьбу), они лучший способ сохранить состояние в нескольких вызовах функций, сохраняя при этом инкапсуляцию.
Даже с резьбой, вы можете сделать трюки в функции (например, выделение конкретных данных потока в пределах функции), чтобы сделать ее работоспособной без необходимости излишнего вмешательства в функции.
Единственные другие варианты, о которых я могу думать, - это глобальные переменные и каждый раз передавать «переменную состояния» в функцию.
В обоих случаях вы подвергаете внутреннюю работу функции своим клиентам и заставляете функцию зависеть от хорошего поведения клиента (всегда опасное предположение).
Этот ответ сидит некоторое время, я вижу, но это не совсем правильно. Действительно, ключевое слово 'static' выполняет множество задач в C. Однако важная вещь, которую следует различать, это _identifier_, используемый для ссылки на объект, и _storage_, используемый объектом. Ключевое слово 'static' * всегда * ограничивает видимость идентификатора текущей областью, будь то на уровне файла или уровне блока. Путаница возникает потому, что 'static' также изменяет _storage_ _duration_ объекта, когда он используется с переменной в области _block_. Обратите внимание на разницу. _identifier_ и _storage_. –
Один из способов запомнить это различие - помнить, что на уровне _block_ ключевое слово 'auto' является значением по умолчанию для идентификаторов уровня _block_ _unless_, которое переопределяется явным использованием ключевого слова' static'. Я подозреваю, что если ключевое слово 'auto' всегда требовалось присутствовать, если присутствовало' static', то уровень замешательства по двойному значению 'static' был бы значительно сокращен. –
@ Грег, я не уверен, что согласен с этим, хотя это всегда возможно, я неправильно понял ваши намерения. 'static' имеет нулевой эффект на видимость идентификатора в _block._ Это тот факт, что он находится в блоке, который ограничивает его видимость для этого блока, а' static' на самом деле не меняет этого. Внедрение переменной уровня блока в статические изменения _only_ длительность его хранения. – paxdiablo