如何在位级表示变量的名称/内存地址?

时间:2012-01-31 17:00:00

标签: c variables memory-address

这可能是一个愚蠢的问题,但我对编程很新,所以请耐心等待。

让我们说,为了论证我正在谈论用C编码......

我理解(系统相关)一个int占用4个字节,或32位内存。

然而,这里有两件事令我感到困惑。这段内存有一个特定的内存地址(也就是32位),如果将这个int存储在一个变量中,那么它也有一个与之关联的名称。

e.g。 int myInt = 5;

我的问题是 - 在位级别表示的内存地址和变量名称的位置和位置是什么?在编译代码时,编译器是否基本上说:“好的myInt引用地址0xffffff”并且基本上替换机器代码中的内存地址?即使是这种情况,我仍然对如何表示内存地址本身感到困惑......

我希望我的困惑在哪里清楚!

2 个答案:

答案 0 :(得分:4)

理论上,答案是“它依赖于实现”。每个C编译器决定采用的最佳方法 - 只要它表现出正确的行为,你到达那里并不重要。

实际上,您可能不会在已编译的程序中看到对变量名称的引用。这是因为处理器不需要知道或关心您为执行程序而分配的变量名称。它的运行水平要低得多:它只需要了解要执行的指令和顺序。因此,包含这些信息是一种多余的奢侈浪费,只会夸大程序的大小。

有三种基本情况,我将在下面列举。我还将描述典型编译器可能会执行的操作,但请记住它依赖于实现,并且通常编译器只要表现出正确的标准行为就可以执行任何操作。

  • 对于局部变量,作为编译过程的一部分,编译器将每个变量名称(例如“int foo;”)替换为对该变量分配的相应内存(“内存地址0x482c”)。对此值的赋值或引用通常只能引用相应的地址。

  • 对于非局部变量,编译器执行额外的分辨率以确定如何发现,但通常不会直接存储变量或函数的名称。

  • 对于根本不是变量的东西(结构,方法等),编译器会根据所做的决策和已设置的参数执行不同的分辨率步骤和优化。但是,这里也没有存储变量或函数的名称;它只是用适当的参考文献替换它。

在某些情况下,在编译器的输出中包含变量名称很有用,就像在调试时一样。在这些情况下,会创建调试符号表。这是一种将地址映射到对人类有意义的名称的方法,这样当事情崩溃时,您可以看到“Stacktrace:function foo()...”而不是“Stacktrace:内存地址0x4572 ......”。

在具有元编程功能的语言中,如C#,Ruby或Java, names 通常会成为与对象一起存储的元数据的一部分,而不是仅仅使用查找替换每个引用。内存地址。当您想要在运行时在C中几乎不可能执行某些巧妙的技巧时,该元数据会派上用场,例如询问“此集合中的哪些对象具有名为foo的字段?”。

答案 1 :(得分:1)

在编译代码时,编译器是否基本上说:“好的myInt引用地址0xffffff”并且基本上替换机器代码中的内存地址?

如果堆栈中有myInt,则堆栈指针中的偏移被放在一边。编译器会记住编译该函数时myInt就在那里。

如果myInt具有全局或文件范围,则它将保持myInt,直到链接器可以决定绝对位置。

我仍然对如何表示内存地址本身感到困惑......

内存中的字节数按升序编号。因此,绝对地址或堆栈偏移在位级看起来都像int