函数中传值变量和局部变量的变量不是连续分配的吗?
Are variables for pass by value variables and local variables in a function not allocated continuously?
我想知道变量在堆栈上的分配方式,所以我做了一个小测试程序
#include <iostream>
#include <stdlib.h>
using namespace std;
class test
{
public:
test()
{
}
test(const test &obj)
{
cout << "a clone of test has been created" << endl;
}
};
void foo(test variable_01, test variable_02)
{
cout << "v3 and v4 have not been created" << endl;
char variable_03;
char variable_04;
cout << "v3 and v4 have been created" << endl;
cout << "Adrress of variable 01: " << static_cast<void*>(&variable_01) << endl;
cout << "Adrress of variable 02: " << static_cast<void*>(&variable_02) << endl;
cout << "Adrress of variable 03: " << static_cast<void*>(&variable_03) << endl;
cout << "Adrress of variable 04: " << static_cast<void*>(&variable_04) << endl;
}
int main()
{
test temp;
foo(temp,temp);
return 0;
}
这是结果
a clone of test has been created
a clone of test has been created
v3 and v4 have not been created
v3 and v4 have been created
Adrress of variable 01: 0xbf9dd3ae
Adrress of variable 02: 0xbf9dd3af
Adrress of variable 03: 0xbf9dd37e
Adrress of variable 04: 0xbf9dd37f
这里有两组变量
- 传递值变量的副本:v_01 & v_02 (G1)
- 局部变量:v_03 & v_04 (G2)
根据结果,我们知道G1已经在G2之前分配了(可能v_01 -> v_02 -> v_03 -> v_04)。但是有一些奇怪的事情:
- 每组的每个变量都是连续分配的,但是G1和G2好像离的有点远,我觉得应该都是0xbf9dd3a_ or 0xbf9dd37_ or { 0xbf9dd3ae -> 0xbf9dd3b1} or { 0xbf9dd37e -> 0xbf9dd381}
- G1的地址总是G2的更大地址。我可以根据加载时程序的堆栈工作方式和数据段来解释这一点。这是加载程序的数据段的快捷方式(来源:http://www.inf.udec.cl/~leo/teoX.pdf)。
- 但是如果我上面的解释是正确的,我无法解释为什么在每个组中,变量的地址都是基于它们被创建的时间。 (例如:v_03 在 v_04 之前,所以 v_04 的地址大于 v_03 的地址)
为什么 G1 的地址大于 G2,尽管它是在 G2 之前创建的?
为什么每组的变量都是连续分配的,但是这些组之间的距离有点远?
为什么组中变量的地址顺序与这些组之间的地址顺序不同?
它依赖于编译器而不是标准的一部分。编译器决定数据需要多少内存,为该数据保留内存块,并决定如何分配它。
在 C 中(不确定 C++ 但我怀疑它是相似的),单独对象的地址之间没有关系。语言 甚至没有定义 它们的顺序关系; >
、<
、<=
和 >=
运算符在用于不指向同一数组的指针上时具有未定义的行为。
至于为什么对象最终在指向它们的指针的数字地址之间具有特定关系,这纯粹是编译器实现细节的结果,它取决于特定的编译器、编译器版本和使用的选项。
我想知道变量在堆栈上的分配方式,所以我做了一个小测试程序
#include <iostream>
#include <stdlib.h>
using namespace std;
class test
{
public:
test()
{
}
test(const test &obj)
{
cout << "a clone of test has been created" << endl;
}
};
void foo(test variable_01, test variable_02)
{
cout << "v3 and v4 have not been created" << endl;
char variable_03;
char variable_04;
cout << "v3 and v4 have been created" << endl;
cout << "Adrress of variable 01: " << static_cast<void*>(&variable_01) << endl;
cout << "Adrress of variable 02: " << static_cast<void*>(&variable_02) << endl;
cout << "Adrress of variable 03: " << static_cast<void*>(&variable_03) << endl;
cout << "Adrress of variable 04: " << static_cast<void*>(&variable_04) << endl;
}
int main()
{
test temp;
foo(temp,temp);
return 0;
}
这是结果
a clone of test has been created
a clone of test has been created
v3 and v4 have not been created
v3 and v4 have been created
Adrress of variable 01: 0xbf9dd3ae
Adrress of variable 02: 0xbf9dd3af
Adrress of variable 03: 0xbf9dd37e
Adrress of variable 04: 0xbf9dd37f
这里有两组变量
- 传递值变量的副本:v_01 & v_02 (G1)
- 局部变量:v_03 & v_04 (G2)
根据结果,我们知道G1已经在G2之前分配了(可能v_01 -> v_02 -> v_03 -> v_04)。但是有一些奇怪的事情:
- 每组的每个变量都是连续分配的,但是G1和G2好像离的有点远,我觉得应该都是0xbf9dd3a_ or 0xbf9dd37_ or { 0xbf9dd3ae -> 0xbf9dd3b1} or { 0xbf9dd37e -> 0xbf9dd381}
- G1的地址总是G2的更大地址。我可以根据加载时程序的堆栈工作方式和数据段来解释这一点。这是加载程序的数据段的快捷方式(来源:http://www.inf.udec.cl/~leo/teoX.pdf)。
- 但是如果我上面的解释是正确的,我无法解释为什么在每个组中,变量的地址都是基于它们被创建的时间。 (例如:v_03 在 v_04 之前,所以 v_04 的地址大于 v_03 的地址)
为什么 G1 的地址大于 G2,尽管它是在 G2 之前创建的?
为什么每组的变量都是连续分配的,但是这些组之间的距离有点远?
为什么组中变量的地址顺序与这些组之间的地址顺序不同?
它依赖于编译器而不是标准的一部分。编译器决定数据需要多少内存,为该数据保留内存块,并决定如何分配它。
在 C 中(不确定 C++ 但我怀疑它是相似的),单独对象的地址之间没有关系。语言 甚至没有定义 它们的顺序关系; >
、<
、<=
和 >=
运算符在用于不指向同一数组的指针上时具有未定义的行为。
至于为什么对象最终在指向它们的指针的数字地址之间具有特定关系,这纯粹是编译器实现细节的结果,它取决于特定的编译器、编译器版本和使用的选项。