Почему неинициализированная переменная в C все еще производит выход

Я пытаюсь понять, почему, хотя локальная переменная i никогда не была инициализирована в этой программе на C, многие системы распечатывают 0 1 2 3 4 5 6 7 8 9 Может кто-нибудь объяснить, почему это так? Любая помощь приветствуется!

 void foo() { int i; printf("%d ", i++); } int main() { int j; for (j = 1; j <= 10; j++) foo(); } 

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

Например, предполагая:

  1. Не проверяется, инициализируются ли переменные или нет.
  2. Это простая машина стека.
  3. Стек инициализируется равным 0.
  4. Переменная i выделяется в стеке, а не как регистр.
  5. Когда вызывается функция, она не инициализирует стек.

В таком случае i буду ссылаться на одно и то же место в стеке каждый раз, начнется как 0, и одно и то же место в стеке будет увеличиваться каждый раз на единицу.

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

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

В моей системе это дает эти значения.

 2009288233 2009288234 2009288235 2009288236 2009288237 2009288238 2009288239 2009288240 2009288241 2009288242 

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

Целое значение, равное нулю, – удача. Это может быть любая другая стоимость мусора.

Поведение не определено и не будет работать в другой системе.

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

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

Как отмечали другие, это неопределенное поведение, поэтому нет твердого ответа.

Тем не менее, вы, вероятно, правы, что наиболее распространенные значения, которые вы получите, будут от 0 до 9. Это произойдет, потому что ОС обнуляет память, занимаемую стеком, прежде чем ваша программа получит ее. foo() представляет собой самый глубокий вызов, который был сделан, поэтому он использует память, которая не была затронута после того, как ОС обнуляла ее, поэтому при первом вызове она, скорее всего, будет содержать нуль.

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

Синус – это неопределенное поведение, ничто из этого не гарантируется вообще, но да, это, вероятно, по крайней мере немного более вероятно, чем нет.