static
средства, что будет одна копия VAL
создана для каждого исходного файла, в который это включено. Но это также означает, что несколько включений не приведут к повторным определениям VAL
, который столкнется во время ссылки. В C без static
необходимо было бы удостовериться, что только один исходный файл определил VAL
, в то время как другие исходные файлы объявили его extern
. Обычно можно было бы сделать это путем определения его (возможно с инициализатором) в исходном файле и поместил бы extern
объявление в заголовочном файле.
static
переменные на глобальном уровне только видимы в их собственном исходном файле, добрались ли они там через то, чтобы включать или были в основном файле.
Примечание редактора: В C++, const
объекты ни с static
, ни с extern
ключевые слова в их объявлении неявно static
.
static
и extern
наклеивает ограниченные по объему файлом переменные, определяют, доступны ли они в других единицах перевода (т.е. другой .c
или .cpp
файлы).
static
дает переменную внутреннюю связь, скрывая его от других единиц перевода. Однако переменные с внутренней связью могут быть определены в нескольких единицах перевода.
extern
дает переменную внешнюю связь, делая его видимым к другим единицам перевода. Обычно это означает, что переменная должна только быть определена в одной единице перевода.
значение по умолчанию (когда Вы не определяете static
или extern
) является одной из тех областей, по которым отличаются C и C++.
В C, ограниченные по объему файлом переменные extern
(внешняя связь) по умолчанию. Если Вы используете C, VAL
static
, и ANOTHER_VAL
extern
.
В C++, ограниченные по объему файлом переменные static
(внутренняя связь) по умолчанию, если они const
, и extern
по умолчанию, если они не. Если Вы используете C++, и VAL
и ANOTHER_VAL
static
.
Из проекта спецификация C:
6.2.2 Связи идентификаторов...-5-, Если объявление идентификатора для функции не имеет никакого спецификатора класса памяти, его связь определяется точно, как будто оно было объявлено с экстерном спецификатора класса памяти. Если объявление идентификатора для объекта имеет объем файла и никакой спецификатор класса памяти, его связь является внешней.
Из проекта спецификация C++:
7.1.1 - Спецификаторы класса памяти [dcl.stc]...-6-имя, объявленное в объеме пространства имен без спецификатора класса памяти, имеет внешнюю связь, если это не имеет внутреннюю связь из-за предыдущего объявления и если это не объявляется константой. Objects объявил, что константа и не явно объявленный экстерн имеет внутреннюю связь.
Помехи будут означать, что Вы получаете одну копию на файл, но в отличие от других сказали, что совершенно законно сделать так. Можно легко протестировать это с небольшим примером кода:
test.h:
static int TEST = 0;
void test();
test1.cpp:
#include <iostream>
#include "test.h"
int main(void) {
std::cout << &TEST << std::endl;
test();
}
test2.cpp:
#include <iostream>
#include "test.h"
void test() {
std::cout << &TEST << std::endl;
}
Выполнение этого дает Вам этот вывод:
0x446020
0x446040
Статическое объявление на этом уровне кода означает, что переменная только видима в текущей единице компиляции. Это означает, что только кодируют в том модуле, будет видеть ту переменную.
, если у Вас есть заголовочный файл, который объявляет, переменные помехи и тот заголовок включены в несколько файлов C/CPP, тогда та переменная будет "локальна" для тех модулей. Будут копии N той переменной для мест N, что заголовок включен. Они не связаны друг с другом вообще. Любой код в любом из тех исходных файлов только сошлется на переменную, которая объявляется в том модуле.
В данном случае, 'статическое' ключевое слово, кажется, не предоставляет преимущества. Я мог бы пропускать что-то, но это, кажется, не имеет значение - я никогда не видел ничего сделанного как это прежде.
Что касается встраивания, в этом случае переменная, вероятно, встраивается, но это - то, только потому, что это объявило константу. Компилятор мог бы для, более вероятно, встраивания статических переменных модуля, но это зависит от ситуации и скомпилированного кода. Нет никакой гарантии, что компилятор встроит 'помехи'.
Книга C (бесплатно онлайн) имеет главу о связи, которая объясняет значение 'статических' более подробно (хотя корректный ответ уже дан в других комментариях): http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html
Для ответа на вопрос "помехи означают, что только одна копия VAL создается, в случае, если заголовок включен больше чем одним исходным файлом?"...
НИКАКОЙ . VAL будет всегда определяться отдельно в каждом файле, который включает заголовок.
стандарты для C и C++ действительно вызывают различие в этом случае.
В C, ограниченные по объему файлом переменные являются экстерном по умолчанию. При использовании C VAL статичен, и ANOTHER_VAL является экстерном.
Примечание, что современные компоновщики могут жаловаться на ANOTHER_VAL, если бы заголовок включен в различные файлы (то же глобальное имя, определенное дважды), и определенно жаловался бы, был ли ANOTHER_VAL инициализирован к различному значению в другом файле
В C++, ограниченные по объему файлом переменные статичны по умолчанию, если они - константа и экстерн по умолчанию, если они не. При использовании C++ и VAL и ANOTHER_VAL статичны.
также необходимо принять во внимание то, что обе переменные определяются константа Идеально, компилятор всегда принимал бы решение встроить эти переменные и не включать любое устройство хранения данных для них. Существует большое количество причин, почему устройство хранения данных может быть выделено. Я могу думать...
Предположение, что эти объявления в глобальной области видимости (т.е. не членские переменные), тогда:
статичный означает 'внутреннюю связь'. В этом случае, так как это объявляется константа , это может быть оптимизировано/встроено компилятором. Если Вы опускаете константа тогда, компилятор должен выделить устройство хранения данных в каждой единице компиляции.
Путем исключения статичный связь экстерн по умолчанию. Снова, Вы были сохранены константа мыс - компилятор может оптимизировать/встроить использование. Если Вы отбросите константа тогда, то Вы доберетесь , умножают определенные символы ошибка во время ссылки.
Статичный предотвращает другую единицу компиляции от externing, что переменная так, чтобы компилятор мог просто "встроить" значение переменной, где это используется и не создает устройство хранения данных памяти для него.
В Вашем втором примере, компилятор не может предположить, что некоторый другой исходный файл не будет экстерн это, таким образом, это должно будет на самом деле сохранить то значение в памяти где-нибудь.
Статичный препятствует тому, чтобы компилятор добавил несколько экземпляров. Это становится менее важным с #ifndef защитой, но принятие заголовка включено в две отдельных библиотеки, и приложение связано, два экземпляра были бы включены.
const
переменные в C ++ имеют внутреннюю связь. Таким образом, использование static
не имеет никакого эффекта.
a.h
const int i = 10;
one.cpp
#include "a.h"
func()
{
cout << i;
}
two.cpp
#include "a.h"
func1()
{
cout << i;
}
Если бы это была программа на C, вы бы получили ошибку «множественное определение» для i
(из-за внешней связи).