Вычислите и объясните семантику следующего фрагмента на C (указывать поведение согласно стандарту, возможные неопределённости и как это исправить): int i = 0
Кратко: это объявление и инициализация объекта типа int с присвоением значения 0 \,0\,0. Поведение по стандарту: - Синтаксис: правильное объявление должно заканчиваться точкой с запятой, например int i = 0;\texttt{int i = 0;}int i = 0;. Без `;` — синтаксическая ошибка компилятора. - Если объявление на уровне файла (file scope): это определение объекта с внешней связностью по умолчанию (external linkage) и статической длительностью хранения (static storage duration). Объект инициализируется значением 0 \,0\,0 до начала выполнения программы (стандартная инициализация статических объектов). - Если объявление внутри блока (block scope) без `static`: объект имеет автоматическую длительность хранения; при исполнении оператора объявления ему присваивается значение 0 \,0\,0 в момент, когда выполнение достигает этой строки. - Семантика инициализации: константное целочисленное выражение 0 \,0\,0 преобразуется к типу int\text{int}int и записывается в объект — не неопределённое и не неинициализированное поведение. Возможные проблемы и их исправление: - Если такой текст помещён в заголовок и включён в несколько единиц трансляции, то получатся множественные определения — ошибка линковщика. Исправление: в заголовке дать объявление `extern`, т.е. extern int i;\texttt{extern int i;}extern int i;, а определить объект один раз в одном .c файле как int i = 0;\texttt{int i = 0;}int i = 0;; или сделать объект внутренней видимости в заголовке с `static` (static int i = 0;\texttt{static int i = 0;}static int i = 0;) если вы хотите отдельную копию в каждой единице трансляции. - Если нужно сохранить значение между вызовами функции, но объявление внутри функции — добавить `static`: static int i = 0;\texttt{static int i = 0;}static int i = 0;. - Если забыта инициализация (например `int i;` в блоке) — значение будет неопределённым; решение — явно инициализировать. Итого: сам по себе фрагмент (правильно записанный как int i = 0;\texttt{int i = 0;}int i = 0;) определён и имеет поведение, описанное выше — UB тут нет.
- Синтаксис: правильное объявление должно заканчиваться точкой с запятой, например int i = 0;\texttt{int i = 0;}int i = 0;. Без `;` — синтаксическая ошибка компилятора.
- Если объявление на уровне файла (file scope): это определение объекта с внешней связностью по умолчанию (external linkage) и статической длительностью хранения (static storage duration). Объект инициализируется значением 0 \,0\,0 до начала выполнения программы (стандартная инициализация статических объектов).
- Если объявление внутри блока (block scope) без `static`: объект имеет автоматическую длительность хранения; при исполнении оператора объявления ему присваивается значение 0 \,0\,0 в момент, когда выполнение достигает этой строки.
- Семантика инициализации: константное целочисленное выражение 0 \,0\,0 преобразуется к типу int\text{int}int и записывается в объект — не неопределённое и не неинициализированное поведение.
Возможные проблемы и их исправление:
- Если такой текст помещён в заголовок и включён в несколько единиц трансляции, то получатся множественные определения — ошибка линковщика. Исправление: в заголовке дать объявление `extern`, т.е. extern int i;\texttt{extern int i;}extern int i;, а определить объект один раз в одном .c файле как int i = 0;\texttt{int i = 0;}int i = 0;; или сделать объект внутренней видимости в заголовке с `static` (static int i = 0;\texttt{static int i = 0;}static int i = 0;) если вы хотите отдельную копию в каждой единице трансляции.
- Если нужно сохранить значение между вызовами функции, но объявление внутри функции — добавить `static`: static int i = 0;\texttt{static int i = 0;}static int i = 0;.
- Если забыта инициализация (например `int i;` в блоке) — значение будет неопределённым; решение — явно инициализировать.
Итого: сам по себе фрагмент (правильно записанный как int i = 0;\texttt{int i = 0;}int i = 0;) определён и имеет поведение, описанное выше — UB тут нет.