(排版不好,见谅)
先说简单的:
像这样 int i = 0; 的语句编译器会将变量 i 放入棧中,当过了它的作用域之后会自动释放它在棧中所占的空间。
再有:我们定义了一个类 A ,然后执行语句 A a = new A; 那么 a 这个变量就被编译器丢到了堆中。
此时 a 中所占的空间只能靠我们自己释放。
再比如我们定义一个数组 int _i_arr[5]; 毫无疑问那么这个数组也会放到棧中(好象是废话)。
如果这两句语句连续起来
int i = 0;
int _i_arr[5];
那么在棧中变量的位置大致上就是
0x000000:
0x00004b: _i_arr(此处向上还有 4*5 个字节属于 _i_arr)
0x000050: i = 0
0xffffff:
编译器按照变量定义的顺序在内存中由高地址向低地址方向进行字节占用。
如果变态一点这样写
int _i_v_arr[-1];
int i = 0;
int _i_arr[5];
编译器不支持,呵呵。换种方式:
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
int i = 0;
int _i_arr[5];
return 0;
}
呵呵,这下支持了(g++),我们骗过了编译器。但是回过头来想想 _i_v_arr 是在运行时才能确定大小的,
那它实在堆上还是在棧上呢?从语法上来看应该是在棧上的。那它在内存中的布局是怎么样的呢?
0x000000:
0x000038: _i_v_arr
0x00004b: _i_arr(此处向上还有 4*5 个字节属于 _i_arr)
0x000050: i = 0
0xffffff:
按照我们之前得出的规律:编译器按照变量定义的顺序在内存中由高地址向低地址方向进行字节占用。
但是这里就违反了,本来 _i_v_arr 是最先定义的,按理说应该在变量 i 的下面(比0x000050要大)
,但是_i_v_arr去跑到了最上面。再定义一个数量是不确定的数组
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
int _i_v_arr_1[getInt()];
int i = 0;
int _i_arr[5];
return 0;
}
通过观察我们发现,在内存中的 _i_v_arr_1 在 _i_v_arr 的上面(_i_v_arr_1 的地址小于 _i_v_arr 的地址)
如果单看这两个动态数组,那他们在内存中位置是符合我们之前的结论的。
于是我们这样理解,编译器在入棧的时候先在编译时期按照能够明确的变量一次入棧,然后再将到运行时才能明确的变量进行入棧。
另外还有个 sizeof() 函数的问题:
int i = 0;
cout << sizeof(i) << endl;
输出是 4.
再看下面:
int i = -1;
if(i < sizeof(i))
{
cout << "i < sizeof(i)" << endl;
}else
{
cout << "i > sizeof(i)" << endl;
}
按常理来讲,-1 是肯定小于 sizeof(i),但是结果正好跟我们预料的相反。因为sizeof(i)返回的是无符号类型,
跟 INT 做比较运算就会将 i 做转换,此时进行比较的 i值已经不是 -1 了。这点一定要注意。
再有代码:
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
cout << sizeof(_i_v_arr) << endl;
int i = 0;
int _i_arr[5];
return 0;
}
此时的sizeof居然可以输出 -4 ,天哪。
很奇怪,当 sizeof 返回小于0的值得时候跟 int 的比较就很正常,但是当 sizeof 的返回值大于等于0的时候就会有 int 类型与无符号类型进行类型转换的问题。
我估计这是 G++ 的BUG。