【问题标题】:Where are variables? Where is their value?变量在哪里?他们的价值在哪里?
【发布时间】:2015-07-25 15:35:26
【问题描述】:

我知道一个变量是一个与相关符号名配对的存储位置,现在我写下这个

int a=8;

我的问题是:

8 在哪里? 8的地址和a的地址一样吗?

【问题讨论】:

  • 8 是整数文字,a 是变量。
  • 谢谢!但是我怎么知道内存中的a和内存中的8。
  • 它可以进入代码或数据部分,并且可以用于初始化。
  • 这可能会回答你的问题:stackoverflow.com/a/11965675/1771055
  • 对自插式感到抱歉,但这可能会澄清一些事情:stackoverflow.com/questions/29247824/…。它还介绍了一个简单的指针示例。

标签: c++ c


【解决方案1】:

变量被命名为内存中的位置。换句话说,变量只是一个值的占位符。当你声明

int a = 8;  

8 存储在名为a 的内存位置。可以使用a 从该内存位置访问此整数文字。

    0x12345        <--- Memory address            
+-------------+
|             |
|      8      |
|             |
+-------------+
       a           <--- Name used to access value stored at location 0x12345  

您可以将其视为将分配的值放入带有变量名称的框中。

int a = 1;

【讨论】:

  • 我只知道电脑里满是0和1。所以a必须有一个地址来存储。8也是。
  • @zentionshon 8 是一个值。您可以将 8 存储在某个位置,但数字 8 没有位置。
  • 你可以在一个位置存储一个8,但是数字8没有位置?为什么?我更困惑。
  • @zentionshon;号码8 存储在某个位置。它没有位置,因为它不是变量。
  • 喜欢盒子示例图片。
【解决方案2】:

语句是变量a的定义和初始化。如果我们简单地分解这个过程,它看起来像

int a=8;
  • 声明一个名为a 的变量,类型为int
  • 定义它(分配内存)
  • 用值8 初始化变量。 [FWIW,这里 8 是 int 文字]

在此之后没有单独的8。 a 持有值 8,仅此而已。

【讨论】:

  • 程序怎么知道用值8初始化变量?那 8 必须写在某个地方(例如微控制器中的 ROM)。
  • 我和@rozina有同样的问题,高级程序员看不到我们的想法。
  • @rozina 初始化变量的代码是一条指令,上面写着“将数字 8 存储在位置 xxxx”。
  • @molbdnilo 这意味着数字8存储在指令中,因此代码部分。这可能会回答 zeniton 的问题。
  • @rozina 直到初始化,在执行int a = 8; 之后,int literal 8 作为 instruction 的一部分出现int literal 8 不再存在可访问。变量a具有的值8。根据a 的存储类型,包含值8 的初始化a 的指令可以出现在可执行文件的不同部分中。
【解决方案3】:

在二进制可执行文件空间中

当您在全局范围内说int a=8; 时,8 可能会进入数据部分,该部分稍后将用于在加载可执行文件时初始化a。

当您在本地范围内说int a=8; 时,8 可能会进入代码部分,稍后将用于初始化变量a(可能位于进程的堆栈段中*) 当程序流程到达这行代码时。

有关更多详细信息,您可以研究二进制可执行文件(例如 ELF)的打包方式以及不同的部分。

在进程空间中

没有像文字或8 这样的东西,变量a 有一个地址,8 存储在该地址。这就是您不能获取文字地址的原因。 (例如&amp;8 是错误的,因为它没有地址,它被匿名存储在某个位置或使用可以寻址的变量别名)

* 假设实现使用堆栈作为局部变量,这对于我见过的所有实现都是如此。

【讨论】:

  • 谢谢!你的意思是 a 和 8 存储在内存中的不同位置?而 8 在数据部分或代码集中?“a”存储在哪里?
  • @zentionshon 8 以二进制形式存储。 a 可能会或可能不会在编译后按字面意思存储。如果它具有外部绑定,则将其存储,否则将在编译期间解析。添加运行时基时解析的地址偏移量是我们实际看到的地址(使用%p 打印)。但是名称a 本身在编译或链接(内部/外部链接)后会被剥离,除非您需要它进行调试。
【解决方案4】:

当您声明变量 int a 并将其设置为 8 时,您的计算机实际上会在内存中保留一个放置 8 的位置。您可以通过将地址分配给另一个变量来得出实际位置(内存地址),例如这个:

int* b = &a;

这会将存储a(8)的地址分配给一个新变量b。

如果您使用的是 Visual-Studio,它假定您的标签为 visual c++,您还可以使用板载实用程序使其可见。打开 Register、Assembly 和 Debug 视图

  • 调试 -> 窗口 -> 寄存器
  • 调试 -> Windows -> 反汇编
  • 调试 -> Windows -> 内存 -> Memory1。

通过在反汇编视图中逐步执行您的调用,您实际上可以看到内存中发生了什么。

我使用了一个稍微扩展的代码行示例来强制展示 Visual Studio 以展示有趣的事件:

int a = 8;

//increment the value in a by 1 and assign it to 1
a = a + 1;

//Get the memory address where the 8 has been 
//stored and set it to b
int* b = &a;

【讨论】:

  • 谢谢,非常好的答案!自从我学了一点 8086 asm 之后,我就知道我的问题到底意味着什么。
【解决方案5】:

a 是位置的名称。
8 是应存储在该位置的值。

从int a = 8 生成的代码通常是一条说明“将数字 8 存储在位置 xxxx”的指令,其中“xxxx”是为a 的存储选择的位置。
所以8通常会存储在代码中,并复制到它应该使用的地方。

(有些平台不这样做,实际上是从特定的内存位置复制小数字。在这种情况下,你可以说数字有一个位置,但那是很久以前的事了。 )

【讨论】:

    【解决方案6】:

    a 是一个变量。当您的程序运行时,它位于计算机的 RAM/内存中,并且有一个地址,就像 RAM 中的每个值都有一个地址一样。

    当您的程序运行时,8 被复制到 a,从而复制到 a 在计算机 RAM 中的位置(其内存地址)。 a 地址指向的内存位置现在包含8 的值。

    现在,当您的程序运行时,变量的名称不再重要了。它已被编译器转换为指向某个相对内存位置。因此,在运行时我们使用地址进行对话,尽管我们(人类,而不是计算机)通过使用变量名来表示内存中的那个位置(地址)来节省脑力。

    【讨论】:

      【解决方案7】:

      让我们试着看看一些连续变量的底层细节。

      int a = 8;
      char b[4] = "ABC";
      int c = 4;
      

      a 是一个变量。因此,它在内存中有一个位置,例如0x1012。假设没有意外的优化在这里移动任何东西,那么小端 32 位系统的内存将如何组织

      0x1012  8   // lowest byte of a
      0x1013  0
      0x1014  0
      0x1015  0   // highest byte of a
      0x1016  65  // (or 0x41 ) ASCII for A first byte of b array
      0x1017  66
      0x1018  67
      0x1019  0   // terminating null
      0x101A  4   // lowest byte for c
      0x101B  0
      0x101C  0
      0x101D  0   // highest byte for c
      

      您可以在这里看到作为变量的 a、b 和 c 如何在内存中具有地址,以及为什么 8、4 和“abc”是驻留在变量中的值。

      如果以后你有a=20,内存会这样改变:

      0x1012  4   // lowest byte of a
      0x1013  1
      0x1014  0   // remaining unchanged ...
      

      这里又是 20 没有位置

      【讨论】:

        猜你喜欢
        • 2010-09-19
        • 2020-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-07
        • 2021-12-17
        • 1970-01-01
        • 2012-07-25
        相关资源
        最近更新 更多