Инициализация статической переменной?

Я просто попробовал следующее:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

, Таким образом, это кажется возможным, но Вам, действительно кажется, нужна некоторая поддержка оборудования.

10
задан Lundin 9 September 2014 в 11:26
поделиться

7 ответов

Why the static variables are deterministically initialized and local variables aren't?

See how the static variables are implemented. The memory for them is allocated at link time, and the initial value for them is also provided at link time. There is no runtime overhead.

On the other hand, the memory for local variables is allocated at run time. The stack has to grow. You don't know what was there before. If you want, you can clear that memory (zero it), but that would incur a runtime overhead. The C++ philosophy is "you don't pay for things you don't use", so it doesn't zero that memory by default.

OK, but why are static variables initialized to zero, and not some other value?

Well, you generally want to do something with that variable. But then how do you know if it has been initialized? You could create a static boolean variable. But then it also has to be reliably initialized to something (preferably false). How about a pointer? You'd rather want it initialized to NULL than some random garbage. How about a struct/record? It has some other data members inside. It makes sense to initialize all of them to their default values. But for simplicity, if you use the "initialize to 0" strategy, you don't have to inspect the individual members and check their types. You can just initialize the entire memory area to 0.

This is not really a technical requirement. The semantics of initialization could still be considered sane if the default value is something other than 0, but still deterministic. But then, what should that value be? You can quite easily explain why 0 is used (although indeed it sounds slightly arbitrary), but explaining -1 or 1024 seems to be even harder (especially that the variable may not be large enough to hold that value, etc).

And you can always initialize the variable explicitly.

And you always have paragraph 8.5.6 of the C++ standard which says "Every object of static storage duration shall be zero-initialized at program startup".

For more info, please refer to these other questions:

20
ответ дан 3 December 2019 в 14:53
поделиться

Это связано с концепцией «платить только за то, что вы используете» в C / C ++.

Для статических переменных инициализация может выполняться без генерации кода. Объектный файл содержит начальные значения для переменных в сегменте данных, и когда ОС загружает исполняемый файл, он загружает и отображает этот сегмент данных до того, как программа начнет выполнение.

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

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

Что касается Java, насколько мне известно, переменные являются всегда инициализируется, когда программа входит в их область видимости, независимо от того, статичны они или нет. Единственное существенное различие между ними состоит в том, что статические переменные охватывают всю программу. Учитывая это, поведение у всех одинаково.

Единственное существенное различие между ними состоит в том, что статические переменные охватывают всю программу. Учитывая это, поведение у всех одинаково.

Единственное существенное различие между ними состоит в том, что статические переменные охватывают всю программу. Учитывая это, поведение у всех одинаково.

1
ответ дан 3 December 2019 в 14:53
поделиться

Так что в некоторой степени это всего лишь дизайнерские решения со стороны разработчиков языка. Но вероятные причины для этих решений в Java следующие:

  • для статических переменных / переменных-членов, если вы собираетесь инициализировать их чем-то, тогда ноль - удобное значение, потому что (а) это обычно подходящее значение для обозначения «не установить что-нибудь особенное », и это значение, которое вы бы выбрали в некоторых случаях, например, счетчики; и (b) внутренне, вероятно, что ноль может использоваться для «специальных» значений, особенно для представления null в случае ссылки на объект.
  • для локальных переменных, если они не имеют значения по умолчанию, разрешает правило, которое заставляет программиста для установки некоторого значения перед чтением переменной, что на самом деле может быть полезно, позволяя компилятору обнаруживать определенные ошибки.

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

Я повторяю, однако, в некоторой степени это дизайнерские решения. По сути, они представляют собой компромисс между тем, что может быть удобно для реализаций JVM и удобно для программистов.

NB. В C / C ++ «статические» переменные означают иное, чем статические переменные в Java!

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

Я повторяю, однако, в некоторой степени это дизайнерские решения. По сути, они представляют собой компромисс между тем, что может быть удобно для реализаций JVM и удобно для программистов.

NB. В C / C ++ «статические» переменные означают иное, чем статические переменные в Java!

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

Я повторяю, однако, в некоторой степени это дизайнерские решения. По сути, они представляют собой компромисс между тем, что может быть удобно для реализаций JVM и удобно для программистов.

NB. В C / C ++ «статические» переменные означают иное, чем статические переменные в Java!

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

NB В C / C ++ "статические" переменные означают иное, чем статические переменные в Java!

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

NB. В C / C ++ «статические» переменные означают иное, чем статические переменные в Java!

2
ответ дан 3 December 2019 в 14:53
поделиться

Параграф 8.5.6 стандарта C ++ гласит:

«Каждый объект со статической продолжительностью хранения должен быть инициализирован нулем при запуске программы»

(Стандарт также говорит, что инициализация локальных переменных не определена)

Относительно того, почему, стандарт не говорит;) Можно предположить, что это достаточно легко реализовать без каких-либо дополнительных недостатков.

4
ответ дан 3 December 2019 в 14:53
поделиться

Говоря о java:

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

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

Переменные с собственным типом не могут получить значение null , поэтому нелокальные переменные инициализируются с помощью 0 или false в качестве отката. Конечно, это не лучшее решение, но я не знаю лучшего. ; -)

3
ответ дан 3 December 2019 в 14:53
поделиться

Я понятия не имею о java, и я сомневаюсь, что в java это другое для статики / локальных.

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

1
ответ дан 3 December 2019 в 14:53
поделиться

Это всего лишь предположение, но это может быть так и для статики, так как это легко реализовать и полезно.

Компилятор может совместно разместить все переменные в одном непрерывном область памяти, а затем либо выдать код (один вызов memset () ), чтобы очистить ее перед вызовом main () . Во многих случаях он также может полагаться на особенности формата исполняемого файла операционной системы, если этот формат поддерживает « bss разделы» , которые вместо этого очищаются загрузчиком. Это экономит место в исполняемом файле, у вас может быть

static unsigned char megabyte[1 << 20];

, и исполняемый файл не будет увеличиваться ни на мегабайт.

Для локальных переменных ничего из этого не применимо; они распределяются «на лету» (обычно в стеке), и очистить их было бы пустой тратой ресурсов, поскольку они '

0
ответ дан 3 December 2019 в 14:53
поделиться
Другие вопросы по тегам:

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