Where is prefix-dependent integer parsing defined?
c++, language-lawyer
Solution
`setbase` is defined in C++98 [lib.std.manip]/5, paraphrasing slightly
smanip setbase(int base);
Returns: An object `s` of unspecified type such that [inserting or extracting `s` from a stream behaves as if the following function were called on that stream:]
ios_base& f(ios_base& str, int base)
{
str.setf(n == 8 ? ios_base::oct :
n == 10 ? ios_base::dec :
n == 16 ? ios_base::hex :
ios_base::fmtflags(0), ios_base::basefield);
return str;
}
Okay, so, if `base` is not 8, 10, or 16, then the `basefield` flags are cleared. The effect of a cleared `basefield` for input is defined in [lib.facet.num.get.virtuals], table 55 ("Integer conversions") as equivalent to `sscanf("%i")` on the sequence of characters next available.
C++98 refers to C89 for the definition of `*scanf`, naturally enough. I don't have a PDF copy of C89, but I do have C99, in which section 7.19.6.2 paragraph 12 [the C standard does not have the nice symbolic section names that the C++ standard has] defines `"%i"` to behave the same as `strtol` with base argument 0.
So the good news is, prefix-dependent integer scanning is guaranteed by the standard after `setbase(0)`. The bad news is, iostream formatted input is defined in terms of `*scanf`, which means the dreadful sentence at the end of C99 7.19.6.2p10 applies:
If [the object that receives the result of scanning] does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
(Emphasis mine.) Clearer version of that sentence: input overflow triggers undefined behavior. The C(++) runtime is allowed to crash the program if input to `*scanf` has too many digits! This is (one of several reasons) why I and others keep saying `*scanf` should never be used, and now I have to start saying it about `istream >> int` as well. :-(
The advice that holds for C is even easier to apply in C++: Read entire lines with `std::getline` and parse them by hand. Use the `strtol` family of functions to convert numeric input to machine numbers. (Those functions have predictable behavior on overflow.)
Problem
I have a simple test program (error checks removed): ``` #include <iostream> #include <iomanip> #include <sstream> #include <string> int main() { std::string line; while(std::cin >> line) { int value; std::stringstream stream(line); stream >> std::setbase(0) >> value; std::cout << "You typed: " << value << std::endl; } } ``` Which works great for prefix-dependent integer parsing. It'll parse strings starting with `"0x"` or `"0X"` as hexadecimal and strings starting with `'0'` as octal. This is explained in several resources that I use and have seen. What I haven't been able to find though, is an indication in the C++ standard that this is guaranteed to work. Section 7.20.1.4.3 on `strtol` in the C standard says (6.4.4.1 is the syntax for integer constants) I imagine the extraction operators use this under the hood: If the value of base is zero, the expected form of the subject sequence is that of an integer constant as described in 6.4.4.1, optionally preceded by a plus or minus sign, but not including an integer suffix. This works on the couple of versions of GCC that I've tried, but is it safe to use generally?