wjl*_*wjl 5 c++ iostream ostream
这个问题起源于我ostream & operator << (ostream &, some_type)对C++中使用通常的数值类型输出数值的正确方法的讨论.
我熟悉std :: showbase和std :: showpos在每个基础中的行为,它们基本上是互斥的.即:在十进制中没有显示基数,并且在正数上添加'+'; 而在十六进制或八进制中,显示了基数,但未显示"+"(也不是减号),因为打印类型的值就好像它被转换为无符号类型一样.
例如,这个简单(详细)的程序:
#include <iostream>
int main() {
std::cout << std::dec << std::showpos << std::showbase << int64_t(+5) << std::endl;
std::cout << std::oct << std::showpos << std::showbase << int64_t(+5) << std::endl;
std::cout << std::hex << std::showpos << std::showbase << int64_t(+5) << std::endl;
std::cout << std::dec << std::showpos << std::showbase << int64_t(-5) << std::endl;
std::cout << std::oct << std::showpos << std::showbase << int64_t(-5) << std::endl;
std::cout << std::hex << std::showpos << std::showbase << int64_t(-5) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
使用GCC编译时给出此输出:
+5
05
0x5
-5
01777777777777777777773
0xfffffffffffffffb
Run Code Online (Sandbox Code Playgroud)
这是我一直期望的,多年来一直使用C++,但这是否真的得到了标准的保证,还是这只是常见的行为?例如,符合标准的C++编译器是否可以输出其中一个序列?
+5
+05
+0x5
-5
01777777777777777777773
0xfffffffffffffffb
Run Code Online (Sandbox Code Playgroud)
甚至:
+5
+05
+0x5
-5
-05
-0x5
Run Code Online (Sandbox Code Playgroud)
就ios_base其本身而言,不。showpos并在流上showbase调用单参数setf(\xc2\xa727.5.6.1[fmtflags.manip]/5和/13),两者互不影响。
更深入一点,astd::ostream使用locale::facet::put函数打印一个整数 (\xc2\xa727.7.3.6.2[ostream.inserters.arithmetic]/1),及其实现locale::facet::do_put\n(\xc2\xa722.4.2.2.2[facet.num. put.virtuals]/5) 指定:
\n\n\n用于描述第 1 阶段的所有表格均已排序。即,条件为 true 的第一行适用。当前面的行都不适用时,不带条件的行是默认行为。
\n\n...
\n\n转换说明符具有以下可选的附加限定符,如表 90 中所示。
\n\n\n 表 90 \xe2\x80\x94 数字转换\n\n+------------------------+------------ ------+----------------+\n| 类型 | 状态| stdio 等效 |\n+========================+=====================+= =================+\n| | 旗帜和展会| + |\n| 整型| | |\n| | 旗帜和展示基地| # |\n+------------------------+--------------------+-- ----------------+\n| | 旗帜和展会| + |\n| 浮点类型 | | |\n| | 旗帜和展示点| # |\n+------------------------+--------------------+-- ----------------+\n\n\n\n...
\n\n第 1 阶段末尾的表示由 char\xe2\x80\x99s 组成,该表示将通过调用上面确定的转换说明符
\nprintf(s, val)where来打印。s
在这里,我们看到showpos和showbase位于同一个单元格中,我相信标准隐含地意味着它们位于同一“行”中,因此两者都适用(可以从std::cout << std::showpos << std::showpoint << 6.0以下“行”中看出),并且这两个标志在这里仍然不是相互排斥的。
到目前为止,我们看到showpos和showbase在 C++ 中并不是唯一的,并且实际的格式化行为是由printf (尽管实现不需要使用printf,例如 libc++ 使用sprintf,而 libstdc++ 不需要)定义的,我们必须检查 C标准。
在 C 中,使用+( showpos) 与oand x/ X( octand hex) 未定义,因为 C99 \xc2\xa77.19.6.1/6 和 /8 表示
\n\n\n\n\n
+\n\n\n有符号转换的结果始终以加号或减号开头。...
\n\n\n
o,u,x,X\n\n该
\nunsigned int参数被转换为...
该参数未签名,因此+无法应用。该行为没有写出来,因此它是未定义的。
#将( showbase)添加到d( dec) 也是未定义的行为,如子句 /6 所示:
\n\n\n\n\n
#\n\n结果转换为\xe2\x80\x9替代形式\xe2\x80\x9d。对于
\no转换,...对于x(或X)转换,...对于a、、、、、、和转换,...对于和转换,...A对于其他转换,行为未定义。eEfFgGgG
哎呀。
\n\n因此,不仅两个标志不互斥,而且输出根本没有定义。OP提到的场景2和3可能会发生。在 gcc 和 clang 中,冲突的选项(showposforoct和hex; showbasefor dec)被简单地忽略,这给人一种这两个选项是互斥的错觉,但标准不会保证这一点。
(免责声明:我使用n3242和n1124作为参考,最终标准可能不完全相同)
\n| 归档时间: |
|
| 查看次数: |
372 次 |
| 最近记录: |