Bash: What happens when you type ‘ls *.c’?

A Linux shell goes through many steps when you enter a command, and the use of a wildcard complicates things further!
If a wildcard is used, the shell has to use a process called globbing to expand the wildcard. The most important wildcards are:
*: the asterisk wildcard matches any number of character, zero or more times
?: the question mark wildcard matches a single character
More may exist depending on your shell, check the man pages for more details!
Once the system matches the wildcard to the possible choices, it’s ready to start the interpreting the command. It has to scour .bashrc and your profiles, checking to see if the command you’ve entered is an alias. If it’s not, it checks to see if it’s a built-in shell program. Each shell has a different list of built-in shell programs (https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html gives a list of shell built-in commands, and using the command type can be used to tell you what type of command it is) and these are ran by the shell itself.
If it’s a program from outside the shell, the shell searches through the command paths to find the right command. The $PATH variable gives a list of paths that the system will dig through to find the correct program.
Once it’s determined the command being used, and the path to it, it runs the program completely separate from the shell itself, and takes in the output from the command. In this case, the ls command will search the file system for anything that matches. In this case, it’ll be anything with .c at the end. So foo.c and bar.c will match, but not foobar.ch.
There’s always more detail to go into, but this is a basic tour of how a Linux system interprets commands!