2010-06-04 1 views
21

Интересна об использовании static ключевого слова в рамках предельных для переменных в файл, в С.Причины использовать статические функции и переменные в C

Стандартный способ построить программу C, как я вижу это до:

  • есть куча c-файлов, определяющих функции и переменные, возможно сфера действия ограничена static.
  • имеют кучу h файлов, объявляющих функции и, возможно, переменные соответствующего файла c, для использования других файлов c. Частные функции и переменные не публикуются в h-файле.
  • каждый файл c скомпилирован отдельно в файл o.
  • все файлы o связаны между собой файлом приложения.

Я вижу две причины для признания Gobal в static, если переменная не опубликована в час файла в любом случае:

  • один для удобства чтения. Информируйте будущих читателей, включая меня, что переменная не доступна ни в одном другом файле.
  • Второй способ - не допустить, чтобы другой файл c обновлял переменную как extern. Я полагаю, что компоновщику будет не нравится переменная, являющаяся как extern, так и static. (Мне не нравится идея переустановки переменной, принадлежащей кому-то еще, как extern, это нормально?)

Любые другие причины?

То же самое касается static функций. Если прототип не опубликован в файле h, другие файлы могут не использовать эту функцию в любом случае, поэтому зачем вообще определять ее static? Я вижу две причины, но не более.

+0

Шесть лет спустя, теперь я знаю, что 'static' не ограничивает область, это дает внутреннюю связь. Это похоже, если вы считаете единицу перевода как область действия, но не правильный термин. – Gauthier

ответ

23

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

Переопределение static переменных как extern невозможно, но компилятор (как обычно) дает вам достаточно веревок, чтобы повеситься.

Если я пишу static int foo; в одном файле и int foo; в другой, они считаются различными переменными, несмотря на то же имя и тип - компилятор не будет жаловаться, но вы, вероятно, получите очень спутать позже пытался читать и/или отлаживать код.(Если я пишу extern int foo; во втором случае, что будет не в состоянии связать, если я не объявить нестатический int foo; где-то в другом месте.)

Глобальные переменные редко появляются в заголовочных файлах, но когда они делают, они должны быть объявлены extern. Если нет, в зависимости от вашего компилятора, вы рискуете, что каждый исходный файл, который включает этот заголовок, будет объявлять свою собственную копию переменной: в лучшем случае это приведет к сбою связи (многоточечный символ) и, в худшем случае, несколько запутанных случаев омрачения.

+1

Интересно. Я понимаю, что этот «extern global в файле заголовка» по-прежнему нуждается в определении в файле c, поскольку extern в h-файле делает его простым объявлением. – Gauthier

+1

Вы правы. – crazyscot

7

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

+0

Это как раз одна из двух причин, о которых я упомянул: «во-вторых, чтобы другой файл c не использовал видимый глобальный охват с ограничением по объему, обновив его как« extern ». И я задавался вопросом о качестве такой практики? – Gauthier

+0

@Gaunthier Итак, ваш пост имеет внутренний конфликт, тогда – qrdl

+2

IMO, 'static' имеет то же значение во всех трех известных применениях (файловая переменная, функциональная переменная, функция), а именно:« это имеет ограниченную область действия и имеет постоянную адрес во время выполнения программы ». – Gauthier

1

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

6

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

+0

Также интересно, хотя зависит от платформы (моя цель имеет только одну инструкцию CALL для абсолютного и не далеко/рядом). – Gauthier

+0

, например. gcc может переключать вызов (что-то быстрее) на статические функции на многих платформах. – nos

-1

Мое любимое использование статики - это возможность хранить методы, которые мне не нужны для ввода или создания объекта для использования, как я его вижу, Частные статические методы всегда полезны, когда public static вы должны ставить некоторые больше времени, думая о том, что именно вы делаете, чтобы избежать того, что было определено crazyscot, поскольку вы слишком много веревки и случайно висели сами!

Мне нравится хранить папки для классов-помощников для большинства моих проектов, которые в основном состоят из статических методов для быстрого и эффективного выполнения на лету, никаких объектов не требуется!

+2

Вопрос о C, а не C++. В C нет классов, нет методов и нет частных членов. Более того, в C++ существует разница в статических функциях и статических методах. –

+1

Упс! Я понимаю, что я определенно неправильно понял вопрос. –

0

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

Если вы напишете функцию foo() в файле ac, не делая ее статичной, и функцию foo() в файле bc, не делая ее статической, компоновщик может жаловаться, но если это не так, все вызовы foo() вызовет ту же функцию. Ожидайте отладки вашего кода.

Смежные вопросы