我想知道运营商如何在计算机内部工作?
并且有许多运算符用于执行许多任务,例如“+”用于添加两个数字以及在java中连接两个字符串..那么,它如何区分这些类型的任务?
答案 0 :(得分:3)
你真正要问的是"how do compilers work?" - 运算符是编译器必须解析的一种标记,并且与其他类型的标记(如方法)没有根本的区别 - 实际上,在允许您定义的语言中你自己的运算符,定义通常看起来像一个方法定义。
唯一的区别是运营商可以拥有infix syntax并且需要优先级规则 - 但这只意味着parsing rules比其他令牌更复杂一些。事实上,最后一个链接可能是您问题的最直接和具体的答案。
答案 1 :(得分:1)
编译器知道操作数的数据类型。如果它看到 2+3
这样的表达式,它将确定两个操作数(即 2 和 3 )是整数,因此编译器将生成执行整数加法的可执行代码。如果表达式是 "Hey, " + "Bob!"
,编译器会看到操作数是字符串,如果语言支持字符串添加(例如在Java中),它将生成执行字符串连接的代码。 / p>
还有一些语言可以在程序运行时决定。在某些情况下,有要完成一个运行时,因为编译器在编译时没有足够的信息来决定这个“+”运算符应该做什么。
答案 2 :(得分:0)
通过使用语言解析器,源代码将转换为已编译的代码或内部表示,然后执行。
答案 3 :(得分:0)
计算机语言的语法经过精心设计,以便编译器/解释器可以决定代码对运算符的使用。
根据定义,正确编写的语法代码永远不会含糊不清。
当编译器说'语法错误'时,它告诉你代码是不明确的。
答案 4 :(得分:0)
运算符的工作方式与带参数的函数非常相似。或者,在现代面向对象语言中,就像带有参数的对象上的方法一样。如果你看一下C ++中的方法重载技术,你可以看到这个问题。所以数字+运算符是 - 在一种伪代码中 - 就像这样:
function integer.+(b: integer) {
return ADD self, b;
}
其余的是语法糖。
你有没有带有后缀表示法的惠普计算器?用这些术语来思考它。因此编译器会将a + b转换为(+ a b)或面向a。+(b)的对象。
编译器从两个操作数派生操作的类型(加法,连接),证明类型兼容性(将整数添加到float ok,concat整数和字符串取决于语言)。
然后将代码转换为内部表示和机器代码。
答案 5 :(得分:0)
它基于(获取此)您使用的运算符来区分任务。解析代码时,解析器/编译器会找到运算符并决定如何处理它周围的事物。如果+用于加法和连接,则取决于提供给它的参数。语言决定在混合时要做什么,例如,如果“4”+ 5等于“45”或9。
此外,运营商优先。也就是说,某些运营商的评估比其他运营商更快。有点像你在数学中学到的操作顺序。例如,+和 - 运算符的优先级通常低于*和/(乘法和除法)运算符(即,乘法运算将在加法运算之前发生)。这就是4 * 5 + 2
将等于22而不是28的原因。您可以找到一个运算符优先级表here.这适用于C语言,但对于大多数其他语言应该类似。
还有运营商关联性。这(基本上)是评估相同类型的运算符的顺序。你习惯的大部分都将保持联想。例如:
4 * 5 * 6 * 7
这是左联想的,意思是:
((4 * 5) * 6) * 7
如果有两个或多个具有相同优先级的运算符“连续”(如示例中所示),则将从左到右对它们进行求值。也就是说,首先是4 * 5,然后是20 * 6,然后是120 * 7.右关联运算符的一个例子是指数运算符:
4 ^ 5 ^ 6 ^ 7
这变为
4 ^ (5 ^ (6 ^ 7))
这些从右到左进行评估。如果指数运算符是左关联的,那么这将产生错误的答案。
将关联性视为“括号内的哪一侧”。它们在左侧是左侧关联,右侧是右侧关联。
same link包含每个运营商的关联性。同样,它适用于C语言,但对于您将使用的大多数其他语言,它应该几乎相同。
答案 6 :(得分:0)
包含“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
有时会添加隐式操作,例如类型转换。大多数编译器都会添加一些优化。