При написании программы на C++ я по ошибке забыл инициализировать переменную в функции main(). Переменная хранила результат вывода и всегда возвращала ноль. Я почти уверен, что многие из вас сделали бы это в прошлом. Это распространенная ошибка. После поиска в Google и изучения идеи, лежащей в основе необычного поведения локальной переменной в C++, я обнаружил следующее.

Предположим, у меня есть следующий фрагмент кода.

#include <bits/stdc++.h>
using namespace std;
int main(){
 int a[10];
 cout<<a[0];
}

Если мы скомпилируем и запустим этот код, мы получим большую часть времени в качестве вывода. Но, как правило, он должен возвращать случайное значение.

Правило говорит:

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

В чем причина этого?

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

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

#include <bits/stdc++.h>
using namespace std;
//int var2;
void fun1(){
  int var1 = 10;
  cout << var1<<"\n";
}
void fun2(){
  int var2 ;
  cout<<var2<<"\n";
}
void fun3(){
  int var3 = 9;
  cout << var3<<"\n";
}
int main(){
  fun2();
  fun1();
  fun2();
  fun3();
  fun2();
}

Он вернет вывод как:

0      // var2 (uninitialized local variable)
10     // var1
10     // var2
9      // var3
9      // var2

Это означает, что компилятор сначала присваивает ноль переменной var2(=0), а затем после сохранения var1=10 присваивает то же значение переменной var2(=10).

Перед запуском функции main() компилятор делает много вещей. Поэтому возможно, что многие другие операции (во время компиляции) инициализируют память стека нулем. Поэтому var2 при первом запуске присваивается 0, а после запуска fun1 присваивается все, что недавно было в стеке.

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

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

#include <stdio.h>

int main(void)
{
	int a, b, c, d, e, f, g, h, i, j, k, l;

	printf("a = %d\n", a);
	printf("b = %d\n", b);
	printf("c = %d\n", c);
	printf("d = %d\n", d);
	printf("e = %d\n", e);
	printf("f = %d\n", f);
	printf("g = %d\n", g);
	printf("h = %d\n", h);
	printf("i = %d\n", i);
	printf("j = %d\n", j);
	printf("k = %d\n", k);
	printf("l = %d\n", l);
	return 0;
}

Это результат, который я получил.

Интересно, если мы напишем только что предыдущий код, используя «cout» вместо «printf», мы получим ноль для всех переменных при первом выполнении (это может не дать ноль для всех переменных на вашем ноутбуке). Но если мы используем в программе вместе «printf» и «cout», она может не вернуть ноль. Будет какое-то случайное значение, отличное от нуля. Так что не путайте. Просто помните: переменные не «инициализируются», а просто принимают значение, которое было в их памяти раньше. Как видно из следующего кода и его вывода.

#include <bits/stdc++.h>
using namespace std;
int main()
{
 int a, b, c, d, e, f, g, h, i, j, k, l;
cout<<"a = "<< a<<"\n";
 cout<<"b = "<< a<<"\n";
 cout<<"c = "<< a<<"\n";
 cout<<"d = "<< a<<"\n";
 cout<<"e = "<< a<<"\n";
 cout<<"f = "<< a<<"\n";
 cout<<"g = "<< a<<"\n";
 cout<<"h = "<< a<<"\n";
 cout<<"i = "<< a<<"\n";
 cout<<"j = "<< a<<"\n";
 cout<<"k = "<< a<<"\n";
 cout<<"l = "<< a<<"\n";
return 0;
}

Резюме:

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