Переменные разрешены во время компиляции, времени выполнения методов. ARef имеет тип A, поэтому aRef.Intvalue является временем компиляции, равным 1.
Этот беспорядок обычно появляется, потому что static
ключевое слово служит двум целям.
При использовании на уровне файла он управляет видимость из ее объекта вне единицы компиляции, не продолжительность из объекта (видимость и продолжительность являются терминами неспециалиста, которые я использую во время образовательных сессий, стандарт ISO использует различные термины, которые можно хотеть изучить в конечном счете, но я нашел, что они смущают большинство начинающих студентов).
Объектам, созданным на уровне файла уже, решили их продолжительность на основании того, что они на уровне файла. static
ключевое слово затем просто делает их невидимыми для компоновщика.
, Когда используется в функциях, это управляет продолжительность , не видимость . Видимость уже решена, так как это в функции - это не может быть замечено вне функции. static
ключевое слово в этом случае, заставляет объект быть созданным в то же время, что и уровень файла возражает.
Примечание, что, технически, статичный функциональный уровень не может обязательно появиться до функции, сначала называют (и это может иметь смысл для C++ с его конструкторами), но каждая реализация C, которую я когда-либо использовал, создает его помехи функционального уровня в то же время, что и уровень файла возражает.
кроме того, пока я использую слово "объект", я не имею в виду это в смысле объектов C++ (так как это - вопрос C). Это просто, потому что static
может относиться к переменным или функциям на уровне файла, и мне нужно всеобъемлющее слово для описания этого.
помехи Функционального уровня все еще используются вполне немного - они могут доставить неприятности в многопоточных программах, если это не обслуживается, но, если Вы знаете то, что Вы делаете (или Вы не распараллеливаете), они - лучший способ сохранить состояние через несколько вызовов функции при тихом обеспечении инкапсуляции.
Даже с поточной обработкой, существуют приемы, которые можно сделать в функции (такой как выделение потока определенные данные в функция) для создания ее осуществимой, не выставляя функциональные внутренности излишне.
Единственным другим выбором, о котором я могу думать, являются глобальные переменные и передача "переменной состояния" к функции каждый раз.
и В этих случаях, Вы выставляете внутренние работы функции ее клиентам и делаете функцию зависящей от хорошего поведения клиента (всегда опасное предположение).
Они используются для реализации инструментов как strtok
, и они вызывают проблемы с повторной входимостью...
Думают тщательно перед дурачением с этим инструментом, но существуют времена, когда они являются соответствующими.
Например, в C++, это используется в качестве одного способа получить одиночный элемент istances
SingletonObject& getInstance()
{
static SingletonObject o;
return o;
}
, который используется для решения проблемы порядка инициализации (хотя это не ориентировано на многопотоковое исполнение).
Ad "не был должен функция быть в ее собственном файле"
, Конечно, не, это не имеет смысла. Большая часть точки языков программирования должна упростить изоляцию и поэтому повторное использование кода (локальные переменные, процедуры, структуры и т.д., все делают это), и это - просто другой способ сделать это.
BTW, как другие указали, почти каждый аргумент против глобальных переменных, относится к статическим переменным также, потому что они на самом деле globals. Но существует много случаев, когда нормально использовать globals, и люди делают.
Я нахожу это удобным для одноразового, отложенного, инициализации:
int GetMagic()
{
static int magicV= -1;
if(-1 == magicV)
{
//do expensive, one-time initialization
magicV = {something here}
}
return magicV;
}
, Поскольку другие сказали, это не ориентировано на многопотоковое исполнение во время, он - самый первый вызов, но иногда можно выйти сухим из воды :)
Я думаю, что люди обычно избегают внутренних статических переменных. Я знаю, что strtok () использует один, или что-то как он, и из-за этого является, вероятно, самой ненавистной функцией в библиотеке C.
Другие языки как C# даже не поддерживают его. Я думаю, что идея раньше была, что это было там для обеспечения некоторого подобия инкапсуляции (если можно назвать его что) перед временем языков OO.
Я не хотел бы, чтобы существование статической переменной вынудило меня поместить функцию в ее собственный файл. Что, если у меня есть много подобных функций, каждый с их собственным статическим счетчиком, который я хотел поместить в один файл? Существует достаточно решений, которые мы должны принять относительно того, куда поместить вещи, не нуждаясь в еще одном ограничении.
Вероятно, не ужасно полезный в C, но они используются в C++, чтобы гарантировать, что инициализация пространства имен определила объем помех. И в C и в C++ там problemns с их использованием в многопоточных приложениях.
Некоторые варианты использования для статических переменных:
Я никогда не слышал эту определенную конструкцию, которую называют "внутренняя статическая переменная". Подходящая маркировка, я предполагаю.
Как любая конструкция, это должно использоваться хорошо осведомлено и ответственно. Необходимо знать разветвления использования конструкции.
Это сохраняет переменную объявленной в самом локальном объеме, не имея необходимость создавать отдельный файл для функции. Это также предотвращает объявление глобальной переменной.
, Например -
char *GetTempFileName()
{
static int i;
char *fileName = new char[1024];
memset(fileName, 0x00, sizeof(char) * 1024);
sprintf(fileName, "Temp%.05d.tmp\n", ++i);
return fileName;
}
VB.NET поддерживает ту же конструкцию.
Public Function GetTempFileName() As String
Static i As Integer = 0
i += 1
Return String.Format("Temp{0}", i.ToString("00000"))
End Function
Одно разветвление этого - то, что эти функции не повторно используемы, ни ориентированы на многопотоковое исполнение.
Не больше. Я видел или услышал результаты функциональных локальных статических переменных на многопоточной земле, и это не симпатично.
В написании кода для микроконтроллера я использовал бы локальную статическую переменную для содержания значения подсостояния для конкретной функции. Например, если у меня был обработчик I2C, который назвали, каждый основной раз () работал затем, ему будут содержать его собственное внутреннее состояние в статической локальной переменной. Затем каждый раз, когда это назвали, это проверит то, что указывает, что это было в, и процесс ввод-вывод соответственно (продвиньте биты на выходные контакты, потяните строку, и т.д.).
Все помехи являются персистентными и незащищенными от одновременного доступа, во многом как globals, и по этой причине должны использоваться с осторожностью и благоразумие. Однако существуют, конечно, времена, когда они пригождаются, и они не обязательно заслуживают быть в своем собственном файле.
я использовал один в функции входа фатальной ошибки, которая исправляется к векторам прерывания по ошибке моей цели, например, отделению нулем, Когда эта функция вызвана, прерывания отключены, таким образом распараллеливание является надуманным вопросом. Но повторная входимость могла все еще произойти, если бы я вызвал новая ошибка, в то время как в процессе входа первой ошибки, как то, если средство форматирования строки ошибки повредилось. В этом случае я должен был бы принять более радикальные меры.
void errorLog(...)
{
static int reentrant = 0;
if(reentrant)
{
// We somehow caused an error while logging a previous error.
// Bail out immediately!
hardwareReset();
}
// Leave ourselves a breadcrumb so we know we're already logging.
reentrant = 1;
// Format the error and put it in the log.
....
// Error successfully logged, time to reset.
hardwareReset();
}
Этот подход проверяет по очень маловероятному событию, и это только безопасно, потому что прерывания отключены. Однако на встроенной цели, правило, "никогда не зависают". Эти гарантии подхода (в причине), что аппаратные средства в конечном счете сбрасываются, так или иначе.
Простое использование для этого состоит в том, что функция может знать, сколько раз это назвали.