我只是编写了一些代码来吐出一个wave标头。我开始输入这个:
file << 0x52 << 0x49 << 0x46 << 0x46 << ...
这让我想到:编译器如何区分解释上述内容:
file << 0x52; file << 0x49; file << 0x46; file << 0x46;
......而且这个:
file << (0x52 << 0x49 << 0x46 << 0x46);
当然,这些运营商的所有可能性排列/组合。
我的猜测是,编译器以某种方式知道第一个是正确的,第二个是错误的,但它遵循的是什么规则?
答案 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 <<
。