(反转与否)波兰表示法不被计算机内部使用:它完全是为人类使用的。它之所以受欢迎,是因为它是一种表示电子计算器相当复杂的算术表达式的方法,当时它们还不够复杂,无法理解运算符优先级和括号,就像今天的计算器一样。使用这些计算器“长大”的工程师已经习惯了以这种方式思考,所以很自然地,通用计算机上的第一个计算器程序也以同样的方式工作。
当您用编程语言编写表达式时,解析器(理解该语言的解释器或编译器的部分)将该表达式转换为一棵树,其中树的每个节点都是一个操作,而该树的每个子节点都是一个操作node 是表达式的操作数。例如,
f(3 + 4)
可能是一个“函数调用”节点,它的第一个子节点是名称f,第二个子节点是一个“add”节点。 “add”节点的子节点是“literal”节点(即值),其值为 3 和 4。
这棵树被称为抽象语法树 (AST),因为它的结构与语言的语法是分开的(即语法被抽象掉了)。在像 gcc 这样可以理解几种不同语言的编译器中,每种语言的解析器都会生成相同类型的 AST,而原始语言是使用 RPN,还是数学风格的中缀表示法,或者只使用函数调用都无关紧要。
解析器然后将其提供给后端。在解释器中,后端将一次只评估每个节点,很可能从底部开始。也就是说,首先它将“add”节点及其子节点替换为值 7,然后查找名为 f 的函数,然后将“函数调用节点”及其子节点替换为函数调用的结果。
编译器将树转换为指令序列。在此示例中,它们可能类似于:
将 3 加载到寄存器 0
将 4 加载到寄存器 1
添加寄存器 0 和 1,并将答案放入寄存器 0
跳转到 f 的代码,它的参数需要在寄存器 0 中
使用寄存器 0 中的结果
显然,这些指令并没有那么冗长:它们是用汇编语言编写的,这通常特定于目标体系结构(您正在为其编译的计算机类型)。我不会展示整个汇编程序,但添加指令可能如下所示:
add r0, r0, r1
编译器的最后一步是汇编器,它将汇编程序的每条指令翻译成一个数字,实际的CPU可以理解。
其中没有 RPN 或操作数堆栈。您听到的有关程序使用的“堆栈”(例如本网站名称中的那个)是一个(某种)自动增长的内存区域。程序可以使用它来存储太大而无法放入寄存器的东西,或者会被函数调用清除的东西(因为被调用的函数想要使用您正在使用的寄存器)。
已经有CPU architectures that actually did use a stack,CPU 的汇编语言看起来有点像 RPN。 PostScript 使用的“虚拟机”是一个例子,Lisp Machines 是/曾经是一个真正的硬件例子。不过,当今流行的 CPU 架构都没有以这种方式工作。