When you press Ctrl+C on the command line, nothing exits, but the handler for SIGINT (sigint_sighandler()) sets the exit status to 130 (128 + 2, as DopeGhoti's answer explains) anyway:
if (interrupt_immediately)
{
interrupt_immediately = 0;
last_command_exit_value = 128 + sig;
throw_to_top_level ();
}
And in throw_to_top_level():
if (interrupt_state)
{
if (last_command_exit_value < 128)
last_command_exit_value = 128 + SIGINT;
print_newline = 1;
DELINTERRUPT;
}
When you press Ctrl+C to kill a background process, the shell observes that the process has died and also sets the exit status $? to 128 plus the signal number.
When you press Ctrl+Z to suspend a background process, the shell observes that something has happened to the process: it hasn't died, but the information is reported through the same system call (wait and friends). Here as well, the shell sets the exit status $? to 128 plus the signal number, which is 148 (SIGTSTP = 20).