请考虑以下代码:
constexpr const int* address(const int& r)
{
return &r;
}
int main()
{
int x = 10;
constexpr const int* p = address(x); //error
_getch();
return 0;
}
这是一个错误:"函数调用必须在常量表达式中具有常量值"。确定。
两个问题:
如果' x'声明静态,没有错误。为什么呢?
如何在编译过程中获取变量地址? Aren他们是否在运行时分配?
答案 0 :(得分:11)
如果'x'被声明为静态,则没有错误。为什么呢?
这是因为程序中总有一个x。它有一个地址(在正常条件下.data
段中的某个位置)。
令人困惑的是,static
和extern
关键字都将存储持续时间指定为静态(它们在链接方面有所不同)
如何在编译过程中获取变量地址?它们不是在运行时分配的吗?
在运行时分配具有自动,动态或线程storage durations的变量。静态持续时间变量由编译器分配。 (链接器和操作系统可以更改位置,但是他们知道如何修复所有引用)
答案 1 :(得分:6)
指向static
存储时间的变量的指针 a constexpr
。您可以在以下程序中看到:
int main() {
static int x;
int y;
constexpr int* px = &x; // Compilation is successful
constexpr int* py = &y; // Compilation will fail
}
px
是地址常量表达式。这是一个标准参考:
[5.19p3]:
地址常量表达式是prvalue核心常量表达式 指针类型的计算结果为具有静态的对象的地址 存储持续时间,函数地址或空指针 值,或类型为std :: nullptr_t的prvalue核心常量表达式。
答案 2 :(得分:2)
具有静态存储持续时间的变量的地址在编译时是未知的。 它仅在链接时才知道。 可以在编译时使用指向具有静态存储持续时间的变量的指针,因为地址的确切值无关紧要 - 在编译时不允许指针比较和强制转换。
答案 3 :(得分:0)
因为具有静态存储持续时间(全局或本地静态)的变量的地址在编译时是已知的,并且在程序执行期间不会更改。此外,整个过程中只有一个对象。
对于局部变量,上面所述的内容都没有。它被分配在堆栈帧中,其地址不同。同时也可以有几个这样的帧。
答案 4 :(得分:0)
问题2: “在编译过程中如何获得变量地址?它们不是在运行时分配的吗?”
x放在堆栈上,当堆栈发生变化时,它有不同的地址。如果x未在main()中声明,而在某些其他函数(从不同位置调用)中,则可能会发生这种情况。例如,尝试
#include <iostream>
constexpr const int* address(const int& r)
{
return &r;
}
int f()
{
int x = 10;
const int* p = address(x);
std::cout << "p=" << p << std::endl;
}
int g()
{
int data[1000];
f();
}
main()
{
f();
g();
return 0;
}