关于fixed<<setprecision

学术版

@[无忌](/space/show?uid=60373) ### 我把带括号和数字(5)的写法编译成汇编(GCC 不开优化 & 不开 C++11): ```cpp mov esi, OFFSET FLAT:std::fixed(std::ios_base&) mov edi, OFFSET FLAT:std::cout call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::ios_base& (*)(std::ios_base&)) mov rbx, rax mov edi, 5 call std::setprecision(int) mov esi, eax mov rdi, rbx call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::_Setprecision) movsd xmm0, QWORD PTR [rbp-24] divsd xmm0, QWORD PTR [rbp-32] mov rdi, rax call std::basic_ostream<char, std::char_traits<char> >::operator<<(double) mov esi, OFFSET FLAT:std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) mov rdi, rax call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&)) ``` ### 再把没有括号和数字的写法编译成汇编: ```cpp mov esi, OFFSET FLAT:std::fixed(std::ios_base&) mov edi, OFFSET FLAT:std::cout call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::ios_base& (*)(std::ios_base&)) mov rdx, rax mov eax, 1 movzx eax, al mov esi, eax mov rdi, rdx call std::basic_ostream<char, std::char_traits<char> >::operator<<(bool) movsd xmm0, QWORD PTR [rbp-24] divsd xmm0, QWORD PTR [rbp-32] mov rdi, rax call std::basic_ostream<char, std::char_traits<char> >::operator<<(double) mov esi, OFFSET FLAT:std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) mov rdi, rax call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&)) ``` ### 发现了两点不同 1. 第一个的第六行有一句 `call std::setprecision(int)`,第二个的第六行是 `movzx eax, al` 2. 第一个的第九行是 `call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::_Setprecision)`;第二个的第九行是 `call std::basic_ostream<char, std::char_traits<char> >::operator<<(bool)` 我想突破点就是在这里了。具体是什么原因,我也不是很清楚。 cppreference 上面说 /*unspecified*/。
by Anguei @ 2018-02-25 19:41:41


@[无忌](/space/show?uid=60373) 我觉得这种东西不如去知乎问问 Milo Yip 等大牛
by Anguei @ 2018-02-25 20:12:10


@[yyfcpp](/space/show?uid=53062) @[无忌](/space/show?uid=60373) 问题远没有这么复杂。 编译选项加一条 -Wall -Wextra 然后再编译这个程序: ```cpp #include <iostream> #include <iomanip> main(){ std::cout<<std::fixed<<std::setprecision<<5.0/3.0; } ``` 就会得到一段警告信息 ```plain xxx.cpp|4|warning: the address of 'std::_Setprecision std::setprecision(int)' will always evaluate as 'true' [-Waddress]| ``` 所以,这个程序在输出`5.0/3.0`之前先输出了一个`true`,即`1`。 显然,你说结果大了,是因为你看到的结果是$11.666667$。 而`std::setprecision`在此处并没有起任何效果,精度还是默认的6位。 `std::_Setprecision`是一个`struct`,储存了当前使用的精度,~~cppreference没有细讲,源码不详细,想必实现原理玄学。~~ 如需查询当前输出精度,可以参考[这个函数](http://zh.cppreference.com/w/cpp/io/ios_base/precision)
by middle_set @ 2018-02-25 20:19:57


@[hiuseues](/space/show?uid=47842) 哦!我说为什么那个会 call 一个 bool 的输出流,原来是这样! 在 cout 的时候加一句 std::alphano: ```cpp std::cout << std::boolalpha << std::fixed << std::setprecision << 5.0 / 3.0 << std::endl; // result: true1.66667 ```
by Anguei @ 2018-02-25 21:40:40


@[yyfcpp](/space/show?uid=53062) 额,把 boolalpha 打成 alphano 了,脑抽脑抽
by Anguei @ 2018-02-25 21:41:31


|