How does std::cout convert numerical types to base 10?
I find the libstdc++ (gcc's standard library) source almost unnavigable, but I think the meat of it is done here:
https://github.com/gcc-mirror/gcc/blob/8e8f6434760cfe2a1c6c9644181189fdb4d987bb/libstdc%2B%2B-v3/include/bits/locale_facets.tcc#L794
Which appears to use the good ol' "divide by 10 and print remainder" technique for decimal digits:
do
{
*--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
__v /= 10;
}
while (__v != 0);
To break this down a bit, remember that the char
type is just a number, and when you write a char, it looks the character up in a table. In both the old ASCII and newer UTF-8 character encodings, '0'
is 48, '1'
is 49, '2'
is 50, etc. This is extremely convenient because you can print any digit 0-9 by adding it to '0':
putchar('0' + 3) // prints 3
So, to get each digit, divide by 10 and the remainder is the last digit:
int x = 123;
putchar('0' + (x % 10)) // prints '0' + 3, or '3'
x = x / 10; // x = 12
putchar('0' + (x % 10)) // prints '0' + 2, or '2'
x = x / 10; // x = 1
putchar('0' + (x % 10)) // prints '0' + 1, or '1'
x = x / 10; // x = 0, stop
The snippet from the library is just doing that in a loop.
You'll notice the code prints the digits backwards. That's why the snippet from the library decrements the character pointer each iterator (*--__buf = ...
) - it's starting at the right and printing it in reverse right-to-left.