Under the Hood of GCC: What Happens When You Run -save-temps?
Recently, I compiled my C code with this flag, and my directory suddenly filled up with unexpected files. Like most C programmers, I used…
Under the Hood of GCC: What Happens When You Run -save-temps?
Recently, I compiled my C code with this flag, and my directory suddenly filled up with unexpected files. Like most C programmers, I used to run gcc main.c on autopilot. You hit enter, a a.out file magically appears, and you run your program.
But a lot happens in that split second. GCC hides its tracks by default, deleting the temporary files it creates during the compilation process.
If you want to pull back the curtain and see exactly how your computer turns text into an executable, you can use the -save-temps flag:
gcc -save-temps main.c
Running this command leaves behind four distinct files: main.i, main.s, main.o, and a.out. Each one represents a milestone in the journey from source code to machine code.
Let’s break down exactly what these files are and how you can use them to debug your code.
1. main.i — The Preprocessed Source Code
Before the compiler even looks at your logic, the preprocessor takes a pass at your file. It handles all lines starting with a #.
The main.i file is the result of this first step. If you open it, you will notice it is massive—often thousands of lines long, even if your original file was only ten lines.
What happened inside?
- Header Expansion: The
#include <stdio.h>line is gone. In its place, thousands of lines of raw C code from the standard library headers have been copy-pasted directly into your file. - Macro Substitution: Every
#definemacro you wrote has been expanded into its literal value. - Cleanup: All your comments have been stripped out.
How to use it:
Ever had a complex macro break your code with a cryptic error? Open main.i. It shows you exactly what your code looks like after the macros expand, making preprocessor bugs easy to spot.
2. main.s — The Assembly Blueprint
Once the preprocessor finishes, the actual compiler (cc1) takes over. It translates the massive C code inside main.i into architecture-specific assembly language.
The output is main.s. This file bridges the gap between human logic and hardware execution. It contains low-level instructions like movl, addl, and pushq, customized for your specific CPU (e.g., Intel x86 or ARM).
How to use it:
This is a goldmine for performance tuning. If you want to see if the compiler optimized your loops, or if you want to see how a switch statement compares to an if-else chain in machine logic, main.s gives you the answer.
3. main.o — The Binary Object File
Computers do not read assembly text; they read binary. The assembler takes main.s and translates it into machine code (1s and 0s). The result is main.o.
If you try to open this file in a normal text editor, you will just see a mess of unreadable gibberish.
Why isn’t it executable yet?
While main.o contains the binary version of your code, it is still an incomplete puzzle. If your code calls printf(), main.o knows a function named printf needs to run, but it doesn't actually contain the code for printf. It is a placeholder waiting for missing pieces.
How to use it:
Object files are the secret to fast build times in large projects. If you change one file in a project with 1,000 files, you only need to recompile that single file into a .o file, rather than rebuilding the whole universe.
4. a.out — The Finished Product
The final step is linking. The linker takes your main.o file, grabs the compiled code for standard library functions (like printf), glues them together, and resolves all the memory addresses.
The final, fully functional executable is named a.out (short for assembler output, a historical name that stuck).
How to use it:
This is your actual application. Type ./a.out in your terminal, and your program runs.
Wrap Up
Using -save-temps is like pausing a magic trick frame-by-frame. It demystifies the black box of compilation and reminds us that C is just a high-level abstraction built on top of assembly and raw binary.
Next time your code behaves strangely, don’t just guess what the compiler is doing. Run -save-temps and look at the evidence yourself.
메타데이터
- post_id
- cbfeda6e1e27
- slug
- under-the-hood-of-gcc-what-happens-when-you-run-save-temps-cbfeda6e1e27
- url
- https://medium.com/@aruncse2k20/under-the-hood-of-gcc-what-happens-when-you-run-save-temps-cbfeda6e1e27
- canonical_url
- https://medium.com/@aruncse2k20/under-the-hood-of-gcc-what-happens-when-you-run-save-temps-cbfeda6e1e27
- author_url
- https://medium.com/@aruncse2k20
- status
- ok
- fetched_at
- 2026-06-09 15:37:30