变量的地址需要加载到内存中吗?

时间:2017-02-20 07:55:06

标签: c++ pointers variables

我有一个问题 - 使用以下代码我试图找出存储在某个地址的内容以及我的静态变量存储在这个特定位置的时间。 (我读到静态变量无限存储并且非常惊讶 - 想测试这是否属实)。 代码定义了一个静态变量(它在我的系统上的地址是0x1000020c0 - 这可能是相当随机的,但一直都是这样)

如果我现在想要找出该地址存储的整数值,我必须先用$ number打印出地址,然后给出0x1000020c0。重新/重新解释地址(0x1000020c0)仅提供100!如果地址是在之前打印的,或者我在重新解释/重铸中使用& number。

有人可以解释为什么会这样吗?

int static number = 100;  

//  std::cout << number << std::endl; <- prints 100

//  prints 100 and the address 0x1000020c0 in my case
//  std::cout << number << " " << &number << std::endl;

//  this does not work unless &number is printed previously
//  std::cout << "Value is :  " << *reinterpret_cast<int*>(0x1000020c0) << std::endl;

// this does work and show the correct value (100)
std::cout << "Value is :  " << *reinterpret_cast<int*>(&number) << std::endl;

3 个答案:

答案 0 :(得分:20)

在任何给定的程序中,对象可能或可能不存储在地址0x1000020c0中。无论如何都无法保证。对象的地址在编译时(或可能在链接时)决定。对程序的更改可以更改地址。

如果您从未获取本地静态对象的地址,并且从不修改它,则编译器可能会优化该变量,以便不使用任何内存。如果对象根本不存在,那么它肯定不会存在于内存位置0x1000020c0。

如果以需要对象存在的方式使用对象,它将位于某个内存位置。获取对象的地址通常会触发此类要求。这与物理学中的observer effect非常相似。

如果取消引用未指向对象(适当类型)的指针,则行为未定义。

  

当我打印重铸/重新解释0x1000020c0的值时,它什么都不打印

正如我上面解释的那样,不保证对象存在于内存位置0x1000020c0。

  

即使使用了对象,因为我通过std :: cout&lt;&lt;打印了它的值。数;

访问对象的值并不一定要求对象存在。编译器可能能够证明对象的值是100,因此它可以将该值存储为常量,而不是存储静态对象。

此外,即使静态对象确实存在,它也不一定存在于地址0x1000020c0中,除非你拿地址并观察它。

因此:不要将任意数字转换为指针(除非您在某个具有硬编码内存映射的嵌入式平台上工作)。看到一个程序中对象的地址是0x1000020c0,在另一个程序中不会使0x1000020c0非任意。

答案 1 :(得分:2)

  1. 假设数字的具体地址不是最好的主意。
  2. 在C ++中,函数体内的static是在第一次调用时或第一次C ++程序流遇到变量时创建的。如果从未使用它们,它们永远不会被创建。
  3. 如果可能,编译器可以选择优化static并将其替换为值。

答案 2 :(得分:0)

您在此处缺少一个非常重要的声明 - 您正在运行此代码的平台。

静态变量未被无限存储&#34 ;;它在程序执行期间存储在该位置。如果你在嵌入式平台上运行,你的代码在上电时跳转到main(),那么你就没有任何其他东西会阻碍你。如果您在任何其他平台(Windows,Linux或其他任何平台)上运行,则该程序在程序完成时将变为空闲状态,并且可立即用于其他任何其他平台。

如果你运行你的程序,它完成了,然后再次运行它,那么你可能会获得相同的内存块供你的程序运行。在这种情况下你&# 39; ll获取静态变量的相同地址。如果其他东西在你的第一次运行结束和下一次运行开始之间要求一大块内存(例如Chrome需要更多空间用于你正在浏览的图片),那么你的程序将不会被给予相同的块记忆和变量不会在同一个地方。

DLL变得更有趣。应用相同类型的规则,除了它们适用于加载DLL的持续时间而不是程序执行的持续时间。 DLL可以在启动时加载并保持一直加载,或者可以根据需要由应用程序加载和卸载。

这一切意味着你做了一些非常奇怪的假设。如果在程序中获得静态变量的地址,然后程序检查该地址的内容,那么您将始终获得该静态变量中的任何内容。这就是静态变量的工作原理。如果您运行代码两次,那么您将在下次运行时获取该静态变量的位置地址,这是您第二次运行时由程序设置的。在您的程序运行之间,该地址是100%免费使用其他任何东西。

正如其他人已经指出的那样,在此之后,您可能还会看到编译器优化对您所询问的特定行为的影响。但是你问这个特定行为的原因是你似乎误解了静态变量的工作原理。