@Shpindel_t_800

Декларация и инициализация, в чем различия?

Привет! Изучаю Python как основной язык, но решил в качестве факультатива понемногу постигать и язык C. Насколько мне известно интерпретатор Cpython написан именно на нем. Поэтому интересно было бы в будущем поковыряться там внутри, и посмотреть как все устроено для лучшего понимания. Но на первом же уроке веры в себя, как в программиста, заметно поубавилось. В уроке про переменные прозвучало два термина: Декларация и Инициализация. И как это примерно выглядит в памяти. Например:
int some_v;
Эта конструкция называется декларацией и переменная не инициализирована. Что это значит? получается этой переменной нет даже в памяти и под нее не зарезервировано место?
int some_v = 10;
А в это случае считается что переменная инициализирована, получается теперь под нее выделена память?
Но ведь компилятор же должен что-то делать с просто задекларированной переменной? как то помечать ее, чтобы потом обращаться к ней, в случае присваивания ей значения?
  • Вопрос задан
  • 924 просмотра
Решения вопроса 3
otdameskapizm
@otdameskapizm
Помог ответ? Отметь решением...
Декларация - объявление переменной с указанием идентификатора и типа данных, который в ней будет лежать типа: int i
Инициализация - присвоение ей начального значения: int i = 9
Ответ написан
includedlibrary
@includedlibrary
int some_v;
Эта конструкция называется декларацией и переменная не инициализирована. Что это значит? получается этой переменной нет даже в памяти и под нее не зарезервировано место?

Зависит от того есть ли дальше по коду обращение к данной переменной. Если есть, то независимо от инициализации будет выделена память на стеке, при этом если инициализации не было, то в переменной будет лежать неопределённое значение. Если обращения нет, то компилятор при оптимизации выкинет эту переменную.
Ответ написан
Комментировать
@res2001
Developer, ex-admin
По моему, на русском чаще используют термин объявление, а не декларация. По крайней мере мне так привычнее.
Объявление в одном из возможных переводов на английский звучит как declaration.
https://en.cppreference.com/w/c/language/declarations
https://en.cppreference.com/w/c/language/type

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

Понять различие между объявлением и определением на простом встроенном типе (int) довольно сложно, потому что сам тип уже известен, его не нужно объявлять. Для примера буду использовать структуру.

Кроме того важно где конкретно в коде программы определена переменная - глобально (по отношению к файлу исходного кода) или локально (в функции).
struct s;                     // предварительное объявление
struct s { int v; };       // объявление структуры
strcut s s1;                // определение глобальной структуры
struct s s2 = { 0 };     // определение глобальной инициализированной структуры
int main()
{
  struct s s3;             // определение локальной структуры
}

Предварительное объявление - говорит о том, что где-то есть полное объявление. Тип объявленный только предварительным объявлением - не завершенный (не полный). Нельзя определить переменную по неполному типа. НО можно определить указатель на неполный тип. Но обращаться по указателю на неполный тип нельзя. Но присвоить адрес можно :-) Это можно использовать в своих интересах.
После полного объявления типа уже можно определять переменные этого типа.
s1 - глобальная не инициализированная структура. Память под нее выделяется в секции bss исполняемого файла. В исполняемом файле обычно не выделяется память непосредственно, но сохраняется размер секции. Загрузчик ОС читает размер секции из файла и выделяет память нужного размера. Глобальные не инициализированные переменные на самом деле инициализируются неявно нулем.
s2 - глобальная инициализированная структура. Память под нее выделяется в секции data исполняемого файла. Тут уже не достаточно сохранить информацию о секции, т.к. есть начальные значения. Поэтому такие переменные непосредственно присутствуют в исполняемом файле (точнее выделена память под них и присвоено начальное значение). Есть еще секция rodata - для константных данных.
s3 - локальная не инициализированная переменная. Память под нее выделяется на стеке. Не зависимо от того инициализирована переменная или нет, память выделена, а значит в этой памяти уже что-то лежит - не бывает "пустой" памяти. В случае не инициализированной переменной на стеке, в памяти лежит мусор, который остался тут от прошлых действий.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы