C ++编译器如何在移位位左移/右移位和ostream<< / ostream>>运营商?

时间:2014-07-20 13:07:18

标签: c++ compiler-construction operators ostream

我只是编写了一些代码来吐出一个wave标头。我开始输入这个:

file << 0x52 << 0x49 << 0x46 << 0x46 << ...

这让我想到:编译器如何区分解释上述内容:

file << 0x52; file << 0x49; file << 0x46; file << 0x46;

......而且这个:

file << (0x52 << 0x49 << 0x46 << 0x46);

当然,这些运营商的所有可能性排列/组合。

我的猜测是,编译器以某种方式知道第一个是正确的,第二个是错误的,但它遵循的是什么规则?

2 个答案:

答案 0 :(得分:4)

C ++中的运算符具有优先级和关联性。

表达式

a << b << c << d
解释

(因为<<是左关联的)为

((a << b) << c) << d

所以感谢流的operator<<返回流本身,你会得到&#34;链式输出&#34;看。

例如,赋值运算符是右关联的,因此

a = b = c = d

被解释为

a = (b = (c = d))

请注意,关于对流使用<<运算符,有一个微妙的事实,经常被C ++新手误解。优先级和关联性规则只会影响结果,但不会影响计算结果的顺序。例如在

std::cout << f() << g() << h();
在评估h()之前,g()的评估可能会发生。更糟糕的是,评估订单的想法对于C ++来说是错误的......因为在

std::cout << f(g()) << h(i());

调用的有效序列也是i, g, f, h

答案 1 :(得分:0)

简短回答:来自上下文。


长答案:编写C ++编译器是一项艰巨的任务,因为C ++具有复杂的语义。 首先,如果operator<<的{​​{1}}没有重载,那么该语句将无效。 此外,由于ADL,我们以这种方式调用fstream,否则就是(当然也是有效的)

operator<<

相反,如果左侧是内置的,则无需查看std::operator<<(file, 0x52).operator<<(file, 0x49) [...] 之类的内容

fstream

* friend std::ofstream& operator<<(std::ofstream&, int)* 也可以匹配

因为内置类型(例如unsigned int)的左移行为已明确定义,而用户定义的类型则未定义。

在这种情况下

unsigned int

括号内的表达式在 file << (0x52 << 0x49 << 0x46 << 0x46); 之前被解释为,因为它的优先级高于file <<