Что именно означает «инициализация»? - PullRequest
3 голосов
/ 11 ноября 2019

В моей книге csapp сказано, что если глобальные и статические переменные инициализированы, то они содержатся в разделе .data в перемещаемом объектном файле ELF.

Поэтому мой вопрос заключается в том, что если некоторый код foo.c содержит

int a;
int main()
{
    a = 3;
}`

и example.c содержит,

int b = 3;
int main()
{
...
}

только b, который считается инициализированным? Другими словами, означает ли инициализация объявление и определение в одной строке?

Ответы [ 5 ]

3 голосов
/ 11 ноября 2019

Оба считаются инициализированными

Они получают инициализированные нулями или постоянные инициализированные (короче: если правая часть является выражением постоянной времени компиляции).

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

Для всех других нелокальных статических и локальных переменных потока выполняется нулевая инициализация. На практике переменные с нулевой инициализацией помещаются в сегмент .bss образа программы, который не занимает места на диске и обнуляется ОС при загрузке программы.

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

3 голосов
/ 11 ноября 2019

Это означает именно то, что говорится. Инициализированным объектам длительности статического хранения будут заданы значения инициализации до вызова основной функции. Не инициализированный будет обнулен. Вторая часть оператора фактически зависит от реализации, и реализация имеет полную свободу в том, как она будет архивироваться.

Когда вы объявляете переменную без ключевого слова extern, вы также всегда определяете ее

1 голос
/ 11 ноября 2019

В фрагменте:

int a;
int main()
{
    a = 3;
}

a не инициализировано;ему присвоено . Назначение - это выполнение кода во время выполнения. Например, если main вызываться несколько раз (что не так, но любая пользовательская функция могла бы), тогда a устанавливается на 3 при каждом вызове функции.

Ваш второй фрагмент это инициализация глобальной переменной b, и она будет помещена в сегмент .data.

1 голос
/ 11 ноября 2019

Я отвечу на этот вопрос в общем и полном виде, а не в отношении какого-либо языка программирования

Существует огромное количество путаницы между объявлением, определением и инициализацией. Иногда все они выглядят одинаково, а иногда совершенно по-разному.

Прежде чем понимать различия, очень важно знать две вещи:

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

В общих чертах (независимо от языка или «вещи»)

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

Многие люди предполагают, что объявление + определение = инициализация.

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

В python нет концепции объявления. Нам не нужно ничего объявлять в этом.

Общее значение этих трех значений действует везде, но способ выполнения варьируется от языка к языку и «вещи».

Надеждаэто помогает:)

0 голосов
/ 11 ноября 2019
  • Переменные с статической продолжительностью хранения , которые инициализируются нулем, заканчиваются на .bss.
  • Переменные с статической продолжительностью хранения , которые инициализируются ненулевым значением, заканчиваются на .data.

ПРИМЕЧАНИЕ: стандарт C гарантирует, что еслипрограммист явно не инициализирует переменную со статической продолжительностью хранения, такой как static int a;, затем она неявно инициализируется нулем 1) . Поэтому a заканчивается в .bss.

Примеры здесь .


1) C11 6.7.9

Если объект, имеющий статическую или потоковую длительность хранения, не инициализирован явно, то:

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