If the input is 123, then on each iteration of the loop, it calculates:
n = 0 * 10 + ('1' - '0');
n = 1 * 10 + ('2' - '0');
n = 12 * 10 + ('3' - '0');
assert(n == 123);
The character codes for the digits are always consecutive, so '1' - '0' is 1, etc.
It converts the digits of a number into a number. Get used to the idiom; you will see it a lot in C code.
The code shown is sloppy in a variety of ways:
int readuint()
{
int n = 0;
char c = fgetc(stdin);
do {
n = n * 10 + (c - '0');
} while ((c = fgetc(stdin)) != '\n');
return n;
}
The name indicates it is reading an unsigned integer (uint), but the type used is a signed int. The type of c should be int because fgetc() (and getc() and getchar()) return an int and not a char. There's no way to indicate that it encountered EOF. There's no protection against overflow. There's no protection against non-digits in the input. Fixing all those requires quite a lot of code, but basic self-protection for the code means it should be more like:
int readint(void)
{
int n = 0;
int c;
while ((c = fgetc(stdin) != EOF && isdigit(c))
n = n * 10 + (c - '0');
if (c != EOF && c != '\n')
ungetc(fp, c);
return n;
}
There's still no protection against overflow, but it has rudimentary protection against EOF and non-digits in the input (leaving characters other than a newline or EOF to be reprocessed by putting it back for the next read operation).
'1'-'0' (char) = (int)1? How does this conversion happen? From char to int: is it because we are assigning to an integer container — i.e int n?
As Elchonon Edelson said, the character constants such as '0' and '1' are integer constants in C (they'd be char constants in C++), and the values for '0' and '1' are very often 48 and 49 respectively (but the C standard does not guarantee that!). So, 49 - 48 gives 1, of course.