Когда использовать статическое ключевое слово перед глобальными переменными?

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

Например, допустим, у меня есть файл заголовка со строкой:

const float kGameSpriteWidth = 12.0f;

Должно быть static перед const или нет? Каковы лучшие практики использования static?


person Matt    schedule 06.12.2009    source источник
comment
Обратите внимание, что в C ++ static подразумевается (т.е. static по умолчанию) для всех const-квалифицированных переменных глобального пространства имен, хотя я бы порекомендовал квалифицировать его как static независимо от того, что намерение проясняется.   -  person abc    schedule 22.02.2020
comment
См. Также Как использовать extern для обмена переменными между исходными файлами? В ответах объясняется, как делиться значениями и ключом часть использует заголовок для объявления (но не определения) переменных, которые являются общими. Если у вас нет заголовка для объявления, определение переменной должно быть статическим. Если у вас есть для него заголовок, включите заголовок как там, где определена переменная (это будет только один исходный файл), так и там, где она используется (может быть много исходных файлов).   -  person Jonathan Leffler    schedule 03.05.2020


Ответы (8)


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

person Dirk Eddelbuettel    schedule 06.12.2009
comment
Я не думаю, что это связано с файлами, это связано с модулями компиляции. - person AraK; 07.12.2009
comment
Если переменная не extern, то она недоступна извне C файла. Тогда какой смысл определять его как статический? - person alex; 17.05.2019
comment
@alex Очень хороший вопрос. По умолчанию глобальные переменные являются внешними, но в любом случае рекомендуется помечать их как таковые. - person Austin Salgat; 20.12.2019
comment
@Arak, если быть точным, это связано с модулями компиляции - я считаю, что это правильное название. Я знаю, что в этом вопросе нет тега C ++, но актуальные модули компиляции пришли к новому стандарту C ++, так что лучше не вводить людей в заблуждение. - person Andrey Borisovich; 14.06.2021

Вы не должны определять глобальные переменные в файлах заголовков. Вы должны определить их в исходном файле .c.

  • Если глобальная переменная должна быть видна только в одном файле .c, вы должны объявить ее статической.

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

Пример:

  • example.h

    extern int global_foo;
    
  • foo.c

    #include "example.h"
    
    int global_foo = 0;
    static int local_foo = 0;
    
    int foo_function()
    {
       /* sees: global_foo and local_foo
          cannot see: local_bar  */
       return 0;
    }
    
  • bar.c

    #include "example.h"
    
    static int local_bar = 0;
    static int local_foo = 0;
    
    int bar_function()
    {
        /* sees: global_foo, local_bar */
        /* sees also local_foo, but it's not the same local_foo as in foo.c
           it's another variable which happen to have the same name.
           this function cannot access local_foo defined in foo.c
        */
        return 0;
    }
    
person Tomek Szpakowicz    schedule 06.12.2009
comment
Я думаю, вы упустили суть. Это константа с плавающей запятой, нет ничего плохого в том, чтобы определять ее как static const в файле заголовка и иметь разные копии в каждой единице перевода. Но большинство людей просто использовали бы #define для литерала. - person Steve Jessop; 07.12.2009
comment
Вопрос был: может ли кто-нибудь объяснить, когда вы должны использовать ключевое слово static перед глобальными переменными или константами, определенными в файлах заголовков? Поскольку OP кажется новичком, я просто дал самое основное правило определения глобальных переменных в C.Как вы сами заметили - вы обычно не можете навредить себе, используя глобальные _const_s в файле заголовка (в C это не так просто, в C ++ ). - person Tomek Szpakowicz; 07.12.2009
comment
В конце концов, это всего лишь принудительное исполнение компилятором. А ведь это не что иное, как воля человека ... - person smwikipedia; 30.03.2018
comment
Нужно ли включать example.h в foo.c? - person hammadian; 04.06.2018
comment
@hammadian В этом случае это не обязательно. Тем не менее, это хорошая идея. Это дает компилятору возможность обнаруживать любые расхождения между объявлениями в файле h и определениями в файле c. - person Tomek Szpakowicz; 06.06.2018

Да, использовать статический

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

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

person DigitalRoss    schedule 06.12.2009
comment
компоновщик не видит, что они константы, и не оптимизирует все объекты? - person Trevor Hickey; 05.08.2015
comment
Но они не являются константами, и важно, чтобы компоновщик случайно не объединил частные объекты вместе просто потому, что у них одинаковое имя. Компоновщики вообще не имеют высокоуровневой информации, они имеют дело только с символами, битовыми строками, пробелами и ссылками. Константы вообще не видны компоновщикам, они просто влияют на сгенерированный код во время компиляции. - person DigitalRoss; 06.08.2015
comment
Другой способ сказать это: весь смысл static в том, чтобы разрешить одно и то же имя быть двумя разными объектами в двух разных модулях. - person DigitalRoss; 21.04.2016

Практическое правило для файлов заголовков:

  • объявить переменную как extern int foo; и поместить соответствующую инициализацию в один исходный файл, чтобы получить изменяемое значение, совместно используемое в единицах перевода
  • используйте static const int foo = 42;, чтобы получить константу, которая может быть встроена
person Christoph    schedule 06.12.2009

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

Проверьте это: Ссылка | Единица перевода

person p.j    schedule 02.04.2016

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

Например. представьте, что вы хотите получить доступ к переменной в другом модуле:

foo.c

int var; // a global variable that can be accessed from another module
// static int var; means that var is local to the module only.
...

bar.c

extern int var; // use the variable in foo.c
...

Теперь, если вы объявите var статическим, вы не сможете получить к нему доступ из любого места, кроме модуля, в который скомпилирован foo.c.

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

person AraK    schedule 06.12.2009

Правильный механизм C ++ в анонимных пространствах имен. Если вам нужно что-то локальное для вашего файла, вам следует использовать анонимное пространство имен, а не статический модификатор.

person rmn    schedule 06.12.2009
comment
Я думаю, что этот ответ плохо сформулирован, слишком краток и не по теме (хотя OP не указывает этого, вопрос помечен как C, а не C ++). - person p4010; 11.11.2019

глобальные статические переменные инициализируются во время компиляции в отличие от автоматических

person Captain Comic    schedule 06.12.2009