Есть простой код, в котором используются неинициализированные переменные:
#include <iostream>
void func1();
int main()
{
    std::cout << "    main()" << std::endl;;
    
    int i;
    std::cout << "int\ti = " << i << std::endl;
    
    double d;
    std::cout << "double\td = " << d << std::endl;
    
    unsigned i2;
    std::cout << "unsign.\ti2 = " << i2 << std::endl;
    long int li;
    std::cout << "l int\tli = " << li << std::endl;
    
    func1();
    return 0;
}
void func1()
{
    std::cout << "    func1()" << std::endl;;
    int a;
    std::cout << "int\ta = " << a << std::endl;
    bool b;
    std::cout << "bool\tb = " << b << std::endl;
}
Если его собрать без оптимизации:
c++ -o prog1 prog1.cc, то бинарник выводит
$ ./prog1
    main()
int     i = 0
double  d = 6.95273e-310
unsign. i2 = 0
l int   li = 4197312
    func1()
int     a = 32535
bool    b = 180
Т.е. в теле функции main() переменные типу int, short int, unsigned int, вроде как, инициализируются нулями. Значение остальных переменных, как и положено, неопределенно.
Если же его собрать с оптимизацией (-O1, -O2 или -O3):
c++ -O2 -o prog1 prog1.cc, то бинарник уже выводит
$ ./prog1
    main()
int     i = 0
double  d = 0
unsign. i2 = 0
l int   li = 0
    func1()
int     a = 0
bool    b = 0
Собственно, вопрос: почему переменные сами инициализируются при включении оптимизации? И почему если собрать без оптимизации, в теле функции main() переменные типу int, short int, unsigned int, char, bool, float инициализируются, а переменные типу long int, long long, double, как и положено, не инициализируются?


