4

我花了很长时间学习 TOC 和编译器设计,但还没有完成,但我对这些概念感到满意。另一方面,我对汇编和机器代码的了解非常浅,并且我一直渴望/需要连接两个方面(代码的 HLL 和 LLL 表示),因为我正在学习 C++,非常注意性能和优化讨论。

C++ 是一种静态类型语言:

我的问题是:当我们的变量写成代码语句中的表达式时,所有这些变量(和其他具有标识符的实体)是否在运行时变成,仅仅是寻址到虚拟内存位置的指令(对于静态和全局)和与局部变量的堆栈地址相关的寻址?

我的意思是,在包括语义和句法验证在内的成功编译之后,将运行时的数据作为目标内存字节的保证实体而不考虑任何标识符或任何检查,不再需要符号表是不明智的吗?

如果我的问题似乎是由于缺乏学习努力而导致的问题类型(我希望不是),请告诉我这一点,并告诉我在哪里阅读。如果是这样的话,老实说,因为我现在专注于 C++,还没有机会对低级语言有充分的了解,我提前为此道歉。

4

2 回答 2

3

你很准。一旦编译为机器代码,就不再有任何变量标识符(或变量类型,就此而言)的概念。它只是某个位置的字节。哪个位置由编译器(编译时)根据变量名确定,或者在全局变量的情况下由链接器(链接时)确定。

当然,保留标识符等信息以用于调试目的是很有用的。这正是“使用调试信息进行编译”的含义:当您这样做时,编译器将以某种方式将(冗余)标识符嵌入到生成的代码中,以便调试器可以访问它们。或者将它们放在旁边的单独文件中;其细节取决于调试信息的格式。

于 2016-07-13T13:02:25.273 回答
2

是的,主要是。有一些细节将使标识符不仅仅是地址或堆栈偏移量。

首先,我们在 C++ 中使用 RTTI,这意味着在运行时至少类型的名称可能仍然可用。例如:

const std::type_info &info = typeid(*ptr_interface);
std::cout << info.name() << std::endl;

将打印任何类型的名称*ptr_interface

其次,由于程序的链接方式,目标文件中的符号可能仍然存在于执行映像中。例如,您有使用它的 linux 内核,因为它可以产生堆栈的回溯,包括函数名称。它还使用函数名称的知识,以便能够加载和链接模块。Gnu C 库中存在类似的功能,而不是链接时,它能够在堆栈跟踪中检索函数名称。

在正常情况下,虽然代码不会受到变量原始名称的影响(但编译器当然会发出适合变量类型的代码)。

于 2016-07-13T13:13:39.070 回答