Programming languages 操作员如何工作?

Programming languages 操作员如何工作?,programming-languages,Programming Languages,我想知道操作员在计算机内部是如何工作的 还有许多计算机用来执行许多任务的运算符,比如“+”在java中用于添加两个数字以及连接两个字符串。。那么,它如何区分这些类型的任务呢?编译器知道操作数的数据类型。如果它看到一个表达式,如2+3,它将确定两个操作数(即2和3)都是整数,因此编译器将生成执行整数加法的可执行代码。如果表达式是“Hey,”+“Bob!”,编译器会看到操作数是字符串,如果语言支持字符串加法(如Java),它将生成执行字符串串联的代码 还有一些语言在程序运行时决定这一点。在某些情况下

我想知道操作员在计算机内部是如何工作的


还有许多计算机用来执行许多任务的运算符,比如“+”在java中用于添加两个数字以及连接两个字符串。。那么,它如何区分这些类型的任务呢?

编译器知道操作数的数据类型。如果它看到一个表达式,如
2+3
,它将确定两个操作数(即23)都是整数,因此编译器将生成执行整数加法的可执行代码。如果表达式是
“Hey,”+“Bob!”
,编译器会看到操作数是字符串,如果语言支持字符串加法(如Java),它将生成执行字符串串联的代码


还有一些语言在程序运行时决定这一点。在某些情况下,它必须在运行时完成,因为编译器在编译时没有足够的信息来决定这个“+”操作符应该做什么。

通过使用语言解析器,源代码被转换为编译代码或内部表示,然后执行。

计算机语言的语法经过仔细设计,以便编译器/解释器可以决定代码所指的运算符的使用

根据定义,正确编写的语法代码永远不会含糊不清


当编译器说“syntax error”时,它告诉您代码是不明确的。

运算符的工作方式非常类似于带参数的函数。或者,在现代面向对象语言中,类似于带有参数的对象上的方法。例如,如果您在C++中查看方法重载技术,您可以看到这一点。所以数字+运算符是一种伪代码,类似这样:

function integer.+(b: integer) {
   return ADD self, b;
}
剩下的是句法上的糖

您有过带后缀符号的HP计算器吗?用这些术语来考虑它。因此,编译器将a+b转换为(+AB),或将面向对象转换为a++(b)

编译器从两个操作数派生操作类型(加法、concatation),证明类型兼容性(add integer to float ok,concat integer和string取决于语言)


然后,它将代码转换为内部表示和机器代码。

您真正想问的是-运算符是编译器必须解析的一种标记,与其他类型的标记(如方法)没有根本区别-事实上,在允许您定义自己的运算符的语言中,该定义通常看起来像方法定义


唯一的区别是操作符可以有一个and并需要优先规则——但这只意味着它比其他标记要复杂一点。事实上,这最后一个链接可能是对您的问题最直接、最具体的回答。

它根据您使用的操作员来区分任务。解析代码时,解析器/编译器会找到运算符并决定如何处理它周围的内容。如果+同时用于加法和串联,则它将取决于提供给它的参数。当它是一个混合体时,语言决定要做什么,例如,“4”+5等于“45”或9

此外,运算符具有优先权。也就是说,某些操作符比其他操作符更快地得到评估。有点像你在数学中学到的运算顺序。例如,+和-运算符的优先级通常低于*和/(乘法和除法)运算符(也就是说,乘法运算将发生在加法运算之前)。这就是为什么
4*5+2
将等于22而不是28。您可以找到一个运算符优先级表,这是针对C语言的,但对于大多数其他语言应该是类似的

还有运算符关联性。这是(基本上)对相同类型的运算符求值的顺序。大多数你习惯的都是左关联的。例如:

4 * 5 * 6 * 7 4 * 5 * 6 * 7 这是左关联的,意思是:

((4 * 5) * 6) * 7 ((4 * 5) * 6) * 7 如果“一行”中有两个或多个具有相同优先级的运算符(如示例中所示),则将从左到右对它们求值。也就是说,先是4*5,然后是20*6,然后是120*7。右关联运算符的一个示例是指数运算符:

4 ^ 5 ^ 6 ^ 7 4 ^ 5 ^ 6 ^ 7 这就变成

4 ^ (5 ^ (6 ^ 7)) 4 ^ (5 ^ (6 ^ 7)) 这些将从右到左进行评估。如果指数操作符是左关联的,这将产生错误的答案

把关联性想象成“括号在哪一边”,左边表示左关联,右边表示右关联


其中包括每个操作符的关联性。同样,它适用于C语言,但对于您将要使用的大多数其他语言,它应该几乎相同。

包含“A+b*(C-d)”等运算符的字符串是一个表达式。编译器解析表达式并创建称为抽象语法字符串的中间结构:

          +
         / \
        a   *
           / \
          b   +
             / \
            c   d
借助语法树对表达式进行求值。叶子的类型(a、b、c、d)决定了需要哪种操作。此信息用于计算表达式(对于解释程序)或创建机器代码:

get c  ; get variable c in a register
add d  ; add variable d
mul b  ; multiply with variable b
add a  ; add variable a
store restult ; store the restult

有时会添加隐式操作,如类型转换。大多数编译器都添加了一些优化。

好吧,语法错误并不一定意味着代码不明确。