Since you specifically mentioned 'By the end of the day I need to transform my C code to a language that specifically my CPU should understand,' I'll explain a little about how compilers work.
Typical compilers do a few things.
First, they do something called lexing. This step takes individual characters and combines them into 'tokens' which are things the next step understands. This step differentiates between language keywords (like 'for' and 'if' in C), operators (like '+'), constants (like integers and string literals), and other stuff. What exactly it differentiates depends on the language itself.
The next step is the parser, which takes the stream of tokens produced by the lexer and (commonly) converts it into something called an "Abstract Syntax Tree," or AST. The AST represents the computations done by the program with data structures that the compiler can navigate. Commonly the AST is language-independent, and compilers like GCC can parse different languages into a common AST format that the next step (the code generator) can understand.
Finally, the code-generator goes through the AST and outputs code that represents the semantics of the AST, that is, code that actually performs the computations that the AST represents.
In the case of GCC, and probably other compilers, the compiler does not actually produce machine code. Instead, it outputs assembly code that it passes to an assembler. The assembler goes through a similar process of lexing, parsing, and code-generating to actually produce machine-code. After all, an assembler is just a compiler that compiles assembly code.
In the case of C (and many others) The assembler is commonly not the final step. The assembler produces things called object files, which contain unresolved references to functions in other object files or libraries (like printf in the C standard library or functions from other C files in your project). These object files are passed to something called a 'linker' whose job it is to combine all of the object files into a single binary, and resolve all of the unresolved references in the object files.
Finally, after all of these steps, you have a complete executable binary.
Note that this is the way that GCC and many, many other compilers work, but it's not necessarily the case. Any program that you could write that accurately accepts a stream of C code and outputs a stream of some other code (assembly, machine code, even javascript) that is equivalent, is a compiler.
Also, the steps are not always completely separate. Rather than lexing and entire file, then parsing the entire result, then generating code for the entire AST, a compiler may do a bit of lexing, then start parsing when it has some tokens, then go back to lexing when the parser needs more tokens. When the parser feels it knows enough, it might do some code generation before having the lexer produce some more tokens for it.