How do I view the output produced by the C pre-processor, prior to its conversion into an object file?
I want to see what the MACRO definitions do to my code.
How do I view the output produced by the C pre-processor, prior to its conversion into an object file?
I want to see what the MACRO definitions do to my code.
gcc -E file.c
or
g++ -E file.cpp
will do this for you. The -E switch forces the compiler to stop after the preprocessing phase, spitting all it’s got at the moment to standard output.
Note: Surely you must have some #include directives. The included files get preprocessed, too, so you might get lots of output.
For Visual C++ the switch is /E which spits the preprocessor output to screen.
You can also call the C Preprocessor directly.
cpp infile outfile
Check out man cpp
for more info.
For GCC,
gcc -E -dM file.c
or
g++ -E -dM file.cpp
should do the job. -dM, as GNU Preprocessor manual puts it, should generate a list of ‘#define’ directives for all the macros defined during the execution of the preprocessor, including predefined macros.
It depends on the compiler you use.
With GCC, you can specify the -E
flag on the command-line to let the compiler produce the pre-processor output.
If using CLion by Jetbrains, you can use the action "clangd: Preprocess current TU"
So hit shift
shift
and start typing clangd...
Best assign it to a shortcut for simpler reuse in preferences->keymap:
Shout out to marcosbento
PS: TU means 'translation unit' (see here LLVM translation unit)
You can check out my script described here:
http://mosermichael.github.io/cstuff/all/projects/2011/09/16/preprocessor.html
It formats the preprocessor output into a (hopefully) readable html document: lines that are different due to preprocessor are marked in the file.
-save-temps
The big advantage of this option over -E
is that it is very easy to add it to any build script, without interfering much in the build itself:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
and now, besides the normal output main.o
, the current working directory also contains the following files:
main.i
is a contains the desired preprossessed file:
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
int myfunc(int i) {
return i + 1;
}
main.s
is a bonus, and contains the desired generated assembly:
.file "main.c"
.text
.globl myfunc
.type myfunc, @function
myfunc:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl $1, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size myfunc, .-myfunc
.ident "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
.section .note.GNU-stack,"",@progbits
-save-temps=obj
If you want to do it for a large number of files, consider using instead:
-save-temps=obj
which saves the intermediate files to the same directory as the -o
object output instead of the current working directory, thus avoiding potential basename conflicts.
For example:
gcc -save-temps -c -o out/subdir/main.o subdir/main.c
leads to the creation of files:
out/subdir/main.i
out/subdir/main.o
out/subdir/main.s
Clearly an Apple plot to take over the world.
-save-temps -v
Another cool thing about this option is if you add -v
:
gcc -save-temps -c -o main.o -v main.c
it actually shows the explicit files being used instead of ugly temporaries under /tmp
, so it is easy to know exactly what is going on, which includes the preprocessing / compilation / assembly steps:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s
Tested in Ubuntu 22.10 amd64, GCC 8.3.0.