Подтвердить что ты не робот

Статические переменные в C и С++

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

4b9b3361

Ответ 1

Нет, нет никакой разницы между C и С++ в этом отношении.

Прочитайте этот SO ответ о том, что означает static в программе на C. В С++ существует несколько других значений, связанных с использованием static для переменных класса (вместо переменных экземпляра).

В отношении глобальных варов static - только с точки зрения распределения памяти (они выделяются в сегменте данных, так как все глобальные переменные). С точки зрения видимости:

static int var;    // can't be seen from outside files
int var;           // can be seen from outside files (no 'static')

Ответ 2

Здесь есть две концепции: "статическая привязка (или область)" и статическое распределение ".

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

Ответ 3

C и С++ - то же самое.

static выполняет две разные вещи.

Для переменных, объявленных вне области функций, он изменяет видимость (привязку) переменной. Переменная будет глобальной переменной, так как она находится за пределами области функции. Если он не является статичным, он будет иметь универсальную привязку (видимость), поэтому любой связанный с ним код может получить к нему доступ (им может потребоваться объявить его extern). Если переменная находится за пределами области действия и является статической, она по-прежнему является глобальной переменной, в которой она всегда существует и сохраняет свое значение, но никакой код за пределами одного и того же модуля компиляции (этот файл .c и любой включенный .h) может получить к нему доступ.

Для переменных, объявленных внутри области функций, static изменяет местоположение, в котором хранится переменная. Если он не является статичным, это будет автоматическая переменная, что означает, что она исчезает, когда функция завершается и возвращается в исходное состояние (в стеке), когда функция вводится снова. Это теряет значение при выходе из функции. А также любые ссылки на него (указатели на него) недействительны после выхода функции. Если переменная, объявленная внутри области функций, является статической, то она делает ее не автоматической, а глобально выделенной. Таким образом, переменная будет существовать после выхода функции и, таким образом, будет сохранять свое значение во всех вызовах функции, а также любые ссылки (указатели) на нее действительны даже после выхода функции. Обратите внимание, что в обоих случаях область действия переменной находится только внутри этой функции, поэтому невозможно получить доступ к ней напрямую (но только через сохраненную ссылку) извне области действия.

Последнее, что статическое действие - это изменение, когда запускается инициализатор (т.е. int foo = 5) для переменной. Для всех случаев, когда распределение является глобальным (каждый случай, за исключением автоматического), инициализатор запускается только один раз, в начале выполнения вашей программы. Он запускается до того, как main() запущен даже, поэтому вы можете получить некоторый не совсем ожидаемый результат, если ваш инициализатор - это не просто постоянное число, а пробег кода. Для автоматического случая инициализатор запускается каждый раз, когда вводится функция, и в этом случае он всегда после ввода main().

Ответ 4

Я хочу добавить ответ на Southern Hospitality Статические переменные в C и С++

следующие замечания:

Использование static для указания "локального перевода" устарело в С++ (href= "http://rads.stackoverflow.com/amzn/click/0201700735" Язык программирования С++: специальное издание, приложение B.2.3, Устаревшие функции).

Вместо этого вы должны использовать неназванные пространства имен:

static int reply = 42; // deprecated

namespace {
    int reply1 = 42;  // The C++ way
}

Как уже говорилось Southern Hospitality, порядок инициализации глобальных объектов undefined. В этой ситуации вы должны рассмотреть возможность использования шаблона href= "http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B" Singleton.

UPDATE: GMan прокомментировал мой ответ:

"Порядок определен для единицы перевода,...": Это действительно ускользнуло от меня, поэтому я просмотрел его на языке программирования С++.

В разделе 9.4.1 "Инициализация нелокальных переменных" проф. Страуструп предполагает, что "функция, возвращающая ссылку, является хорошей альтернативой глобальной переменной":

int& use_count()
{
        static int uc = 0;
        return uc;
}

"Вызов use_count() теперь действует как глобальная переменная, которая инициализируется при ее первом использовании. Например:"

void f()
{
        std::cout << ++use_count() << '\n';
}

В моем понимании это очень похоже на шаблон Singleton.

GMan прокомментировал далее: "Нам нужно ограничить нашу способность создавать эти объекты для одного и обеспечивать глобальный доступ к нему". Имеет ли ограничение на самом деле отношение к чему-либо в проблеме? Нам может понадобиться один глобальный, но кто скажет, что мы не хотим этого в других местах? "

Некоторые цитаты из Singleton (127) (Gamma et al, Design Patterns):

"Шаблон Singleton является улучшением по сравнению с глобальными переменными. Он позволяет избежать загрязнения пространства имен глобальными переменными, которые хранят только экземпляры".

"Шаблон позволяет легко передумать и разрешить более одного экземпляра класса Singleton".

Синглтоны инициализируются в порядке их первого использования.

В Herb Sutter, Andrei Alexandrescu, С++ Coding Standards, в пункте 10 говорится:

"Избегайте общих данных, особенно глобальных данных".

Поэтому я часто использую синглтоны, чтобы избежать глобальных данных. Но, конечно же, поскольку все слишком много, это может быть чрезмерным использованием шаблона Singleton. (Йохшуа Кериевский называет этот "Singletonitis" в своей книге "Рефакторинг для шаблонов".)

ОБНОВЛЕНИЕ 2:

(Извините, но я не могу писать комментарии, поэтому это обновление.)

Jalf написал в своем комментарии: "Банда из четырех людей курила что-то незаконное, когда они писали об одноэлементном узоре".

Очевидно, другие разработчики С++ курили интересные вещества. Например, Херб Саттер (он работал более десяти лет в качестве секретаря и председателя комитета стандартов ISO С++ во время разработки второго стандарта С++, С++ 0x и ведущего архитектора С++/CLI в Microsoft. разработчик модели памяти Prism для платформ Microsoft и расширения Concur для Visual С++ для параллельного программирования), написано в С++ Standards Standards, Item 21:

"Если вам нужна такая переменная (пространство пространства имен), которая может зависеть от другой, рассмотрите шаблон проектирования Singleton, который будет использоваться тщательно, он может избежать неявных зависимостей, гарантируя, что объект будет инициализирован при первом доступе. Тем не менее, Singleton является глобальная переменная в овечьей одежде и нарушается взаимными или циклическими зависимостями".

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

Обратите внимание, что на языке Java глобальные данные даже не существуют. Очевидно, что глобальные данные подставляются/эмулируются с использованием шаблона проектирования Singleton.

(Поскольку я работаю в своей dayjob с командой Java, я стремлюсь к максимальному подобию своих программ на С++ с помощью Java-программ. Например, каждый класс находится в своей собственной исходной файловой/переводческой единице.)

Ответ 5

Не на самом деле прямой ответ на ваш вопрос, но что-то тесно связанное с тем, чтобы следить за тем, чтобы использовать как C, так и С++.

В С++, в отличие от C, глобальные переменные, объявленные как "const", неявно локальны для единицы перевода, AS IF "статический" был использован.

Пример:

// file A
extern const int glob;

// file B
const int glob = 42;

Это будет работать, если вы используете компилятор C, но не с компилятором С++. В С++ переменная glob в файле B не может использоваться из файла A, и компоновщик будет генерировать ошибку "неразрешенной ссылки".