Are std::showbase and std::showpos mutually exclusive?

一个人想着一个人 提交于 2019-12-04 08:17:36

For ios_base itself, no. showpos and showbase calls the single-argument setf (§27.5.6.1[fmtflags.manip]/5 and /13) on the stream, which the two does not affect each other.


Going deeper, a std::ostream uses the locale::facet::put function to print an integer (§27.7.3.6.2[ostream.inserters.arithmetic]/1), and its implementation locale::facet::do_put (§22.4.2.2.2[facet.num.put.virtuals]/5) specifies:

All tables used in describing stage 1 are ordered. That is, the first line whose condition is true applies. A line without a condition is the default behavior when none of the earlier lines apply.

...

The conversion specifier has the following optional additional qualifiers prepended as indicated in Table 90.

                  Table 90 — Numeric conversions

+-----------------------+-------------------+------------------+
| Type(s)               | State             | stdio equivalent |
+=======================+===================+==================+
|                       | flags & showpos   | +                |
| an integral type      |                   |                  |
|                       | flags & showbase  | #                |
+-----------------------+-------------------+------------------+
|                       | flags & showpos   | +                |
| a floating-point type |                   |                  |
|                       | flags & showpoint | #                |
+-----------------------+-------------------+------------------+

...

The representations at the end of stage 1 consists of the char’s that would be printed by a call of printf(s, val) where s is the conversion specifier determined above.

Here, we see that showpos and showbase are in the same cell, which, I believe the standard implicitly mean that they're in the same "line", and thus both applies (it can be seen from std::cout << std::showpos << std::showpoint << 6.0 for the following "line"), and the two flags are still not mutually exclusive here.


So far, we see that showpos and showbase are not exclusive in C++, and the actual formatting behavior is defined by printf (though the implementation doesn't need to use printf, e.g. libc++ uses sprintf, while libstdc++ does not), which we have to check the C standard.

In C, using + (showpos) with o and x/X (oct and hex) is not defined, because C99 §7.19.6.1/6 and /8 says

+

The result of a signed conversion always begins with a plus or minus sign. ...

o, u, x, X

The unsigned int argument is converted to ...

The argument is not signed, so the + cannot apply. The behavior is not written out, so it is undefined.

Adding # (showbase) to d (dec) is also undefined behavior, as clause /6 says:

#

The result is converted to an “alternative form”. For o conversion, ... For x (or X) conversion, ... For a, A, e, E, f, F, g, and G conversions, ... For g and G conversions, ... For other conversions, the behavior is undefined.

Oops.

Therefore, not only the two flags are not mutually exclusive, the output is not defined at all. Scenarios 2 and 3 OP mentioned may happen. In gcc and clang, the conflicting option (showpos for oct and hex; showbase for dec) are simply ignored, which gives one an illusion of the two options being mutually exclusive, but the standard will not guarentee that.

(Disclaimer: I am using n3242 and n1124 as reference, the final standard might not be exactly the same)

Guvante

Bit of googling found me this page which says the following on the subject:

Note that negative integers are not printed as such in octal or hexadecimal. Rather, the internal bit patterns are interpreted as always being positive values.

If this is accurate, it would make sense that showpos would do nothing, why show a + in front of a number that is always positive?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!