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.