Внутренние статические переменные в C, Вы использовали бы их?

Переменные разрешены во время компиляции, времени выполнения методов. ARef имеет тип A, поэтому aRef.Intvalue является временем компиляции, равным 1.

22
задан hhafez 11 February 2009 в 00:38
поделиться

13 ответов

Этот беспорядок обычно появляется, потому что static ключевое слово служит двум целям.

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

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

, Когда используется в функциях, это управляет продолжительность , не видимость . Видимость уже решена, так как это в функции - это не может быть замечено вне функции. static ключевое слово в этом случае, заставляет объект быть созданным в то же время, что и уровень файла возражает.

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

кроме того, пока я использую слово "объект", я не имею в виду это в смысле объектов C++ (так как это - вопрос C). Это просто, потому что static может относиться к переменным или функциям на уровне файла, и мне нужно всеобъемлющее слово для описания этого.

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

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

Единственным другим выбором, о котором я могу думать, являются глобальные переменные и передача "переменной состояния" к функции каждый раз.

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

36
ответ дан paxdiablo 29 November 2019 в 03:44
поделиться

Они используются для реализации инструментов как strtok, и они вызывают проблемы с повторной входимостью...

Думают тщательно перед дурачением с этим инструментом, но существуют времена, когда они являются соответствующими.

9
ответ дан dmckee 29 November 2019 в 03:44
поделиться

Например, в C++, это используется в качестве одного способа получить одиночный элемент istances

SingletonObject& getInstance()
{
  static SingletonObject o;
  return o;
}

, который используется для решения проблемы порядка инициализации (хотя это не ориентировано на многопотоковое исполнение).

Ad "не был должен функция быть в ее собственном файле"

, Конечно, не, это не имеет смысла. Большая часть точки языков программирования должна упростить изоляцию и поэтому повторное использование кода (локальные переменные, процедуры, структуры и т.д., все делают это), и это - просто другой способ сделать это.

BTW, как другие указали, почти каждый аргумент против глобальных переменных, относится к статическим переменным также, потому что они на самом деле globals. Но существует много случаев, когда нормально использовать globals, и люди делают.

7
ответ дан jpalecek 29 November 2019 в 03:44
поделиться

Я нахожу это удобным для одноразового, отложенного, инициализации:

int GetMagic()
{
   static int magicV= -1;

   if(-1 == magicV)
   {
      //do expensive, one-time initialization
      magicV = {something here}
   }
   return magicV;
}

, Поскольку другие сказали, это не ориентировано на многопотоковое исполнение во время, он - самый первый вызов, но иногда можно выйти сухим из воды :)

4
ответ дан DougN 29 November 2019 в 03:44
поделиться

Я думаю, что люди обычно избегают внутренних статических переменных. Я знаю, что strtok () использует один, или что-то как он, и из-за этого является, вероятно, самой ненавистной функцией в библиотеке C.

Другие языки как C# даже не поддерживают его. Я думаю, что идея раньше была, что это было там для обеспечения некоторого подобия инкапсуляции (если можно назвать его что) перед временем языков OO.

1
ответ дан Dave Markle 29 November 2019 в 03:44
поделиться

Я не хотел бы, чтобы существование статической переменной вынудило меня поместить функцию в ее собственный файл. Что, если у меня есть много подобных функций, каждый с их собственным статическим счетчиком, который я хотел поместить в один файл? Существует достаточно решений, которые мы должны принять относительно того, куда поместить вещи, не нуждаясь в еще одном ограничении.

1
ответ дан gbarry 29 November 2019 в 03:44
поделиться

Вероятно, не ужасно полезный в C, но они используются в C++, чтобы гарантировать, что инициализация пространства имен определила объем помех. И в C и в C++ там problemns с их использованием в многопоточных приложениях.

1
ответ дан 29 November 2019 в 03:44
поделиться

Некоторые варианты использования для статических переменных:

  • можно использовать его для счетчиков, и Вы не загрязните глобальное пространство имен.
  • можно защитить переменные с помощью функции, которая получает значение как указатель и возвращает внутренние помехи. Этот whay, которым можно управлять, как значение присвоено. (используйте ПУСТОЙ УКАЗАТЕЛЬ, когда Вы просто захотите получить значение)
1
ответ дан George 29 November 2019 в 03:44
поделиться

Я никогда не слышал эту определенную конструкцию, которую называют "внутренняя статическая переменная". Подходящая маркировка, я предполагаю.

Как любая конструкция, это должно использоваться хорошо осведомлено и ответственно. Необходимо знать разветвления использования конструкции.

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

, Например -

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

Одно разветвление этого - то, что эти функции не повторно используемы, ни ориентированы на многопотоковое исполнение.

1
ответ дан user62572 29 November 2019 в 03:44
поделиться

Не больше. Я видел или услышал результаты функциональных локальных статических переменных на многопоточной земле, и это не симпатично.

1
ответ дан MSN 29 November 2019 в 03:44
поделиться

В написании кода для микроконтроллера я использовал бы локальную статическую переменную для содержания значения подсостояния для конкретной функции. Например, если у меня был обработчик I2C, который назвали, каждый основной раз () работал затем, ему будут содержать его собственное внутреннее состояние в статической локальной переменной. Затем каждый раз, когда это назвали, это проверит то, что указывает, что это было в, и процесс ввод-вывод соответственно (продвиньте биты на выходные контакты, потяните строку, и т.д.).

1
ответ дан Stephen Friederichs 29 November 2019 в 03:44
поделиться

Все помехи являются персистентными и незащищенными от одновременного доступа, во многом как 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();
}

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

1
ответ дан Casey Barker 29 November 2019 в 03:44
поделиться

Простое использование для этого состоит в том, что функция может знать, сколько раз это назвали.

0
ответ дан lillq 29 November 2019 в 03:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: