Pressing C while Ctrl is pressed sends a keypress followed by keyrelease X11 event to the terminal emulator.
Upon that event (generally the keypress one), the terminal emulator writes the 0x3 byte (
^C) to its file descriptor on the master side of the pseudo-tty device.
isig termios setting of the device is on and if the
intr setting is set to that 0x3 byte, then the kernel sends the SIGINT signal to all the members of the foreground process group of the terminal device (another attribute stored in the pty device). In that case, the 0x3 byte will not be available for reading on the slave side of the pty.
It's usually interactive shells that create process groups (with
setpgid()) for shell jobs, and decide which one to put in foreground (with
tcsetpgrp() to set that attribute of the pty device) or not.
For instance when you run at the prompt of an interactive shell:
foo | bar
The shell starts a new process groups with two processes (in which it executes
bar after having connected their stdin/out with a pipe) and puts that group in foreground. Both processes would receive the SIGINT if you pressed Ctrl-C.
foo | bar &
Same but the process group is not put in foreground (and the shell also doesn't wait for it so you can enter other commands). Those processes would not get the SIGINT upon Ctrl-C but could be suspended if they try to read from the tty device.
More reading at: What are the responsibilities of each Pseudo-Terminal (PTY) component (software, master side, slave side)?