從代碼到可執行程序的四個階段:
預處理-->編譯-->匯編-->鏈接
一步完成從代碼到可執行程序:
對c程序來說使用
gcc name.c -o name.exe
執行命令后會生成可執行文件 name.exe。
對c++程序來使用
g++ name.cpp -o name.exe
執行命令后生成可執行文件name.exe。
gcc和g++的區別:
對C程序來說,gcc使用c代碼的方式編譯 ,而g++則使用C++代碼的方式編譯。注意:使用C++的方式編譯C代碼可能會出錯。
對C++程序來說,兩者沒有差別。
四個階段完成從代碼到可執行程序:
源文件b.cpp代碼如下:
#include<iostream> using namespace std; /* 這是一個注釋! */ int main() { cout<<"c++ program!"<<endl; system("pause"); return 0; }
1、預處理
g++ -E(大寫) name.cpp
-E 選項用來對原代碼做預處理操作。使用 g++ -E b.cpp命令后,只會將預處理指操作的結果輸出到屏幕,若想保存操作結果則要搭配-o使用。
預處理主要處理源文件和頭文件中以#開頭的命令(#<iostream>等),並刪除程序中的注釋信息等。
運行 g++ -E b.cpp -o b.i 會生成一個b.i文件
打開b.i文件后可以看到一些信息,發現其中注釋已經被刪掉了,頭文件被替換為好多行代碼。
# 1 "b.cpp" # 1 "<built-in>" # 1 "<command-line>" # 1 "b.cpp" # 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 1 3 # 36 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 3 # 37 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 3 # 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 1 3 # 236 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 3 # 236 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 3 namespace std { typedef long long unsigned int size_t; typedef long long int ptrdiff_t; typedef decltype(nullptr) nullptr_t; ..... ..... ..... ..... ..... extern istream cin; extern ostream cout; extern ostream cerr; extern ostream clog; extern wistream wcin; extern wostream wcout; extern wostream wcerr; extern wostream wclog; static ios_base::Init __ioinit; } # 2 "b.cpp" 2 # 3 "b.cpp" using namespace std; int main() { cout<<"c++ program!"<<endl; system("pause"); return 0; }
2、編譯
g++ -S(大寫) name.cpp / name.i
使用該g++ -S b.cpp 后會自動生成b.s匯編代碼文件,將c++代碼翻譯為匯編代碼。
g++ -S指令並非必須經過預處理后的.i文件,-S選項的功能是令GCC編譯器將指定文件預處理至編譯階段結束。
也就是說g++ -S可以處理.i文件,也可以處理原代碼文件。
.file "b.cpp" .text .section .rdata,"dr" _ZStL19piecewise_construct: .space 1 .lcomm _ZStL8__ioinit,1,1 .def __main; .scl 2; .type 32; .endef .LC0: .ascii "c++ program!\0" .LC1: .ascii "pause\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc main main: .LFB1573: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue call __main leaq .LC0(%rip), %rdx movq .refptr._ZSt4cout(%rip), %rcx call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movq .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(%rip), %rdx movq %rax, %rcx call _ZNSolsEPFRSoS_E leaq .LC1(%rip), %rcx call system movl $0, %eax addq $32, %rsp popq %rbp ret .seh_endproc .def __tcf_0; .scl 3; .type 32; .endef .seh_proc __tcf_0 __tcf_0: .LFB2063: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue leaq _ZStL8__ioinit(%rip), %rcx call _ZNSt8ios_base4InitD1Ev nop addq $32, %rsp popq %rbp ret .seh_endproc .def _Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef .seh_proc _Z41__static_initialization_and_destruction_0ii _Z41__static_initialization_and_destruction_0ii: .LFB2062: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue movl %ecx, 16(%rbp) movl %edx, 24(%rbp) cmpl $1, 16(%rbp) jne .L6 cmpl $65535, 24(%rbp) jne .L6 leaq _ZStL8__ioinit(%rip), %rcx call _ZNSt8ios_base4InitC1Ev leaq __tcf_0(%rip), %rcx call atexit .L6: nop addq $32, %rsp popq %rbp ret .seh_endproc .def _GLOBAL__sub_I_main; .scl 3; .type 32; .endef .seh_proc _GLOBAL__sub_I_main _GLOBAL__sub_I_main: .LFB2064: pushq %rbp .seh_pushreg %rbp movq %rsp, %rbp .seh_setframe %rbp, 0 subq $32, %rsp .seh_stackalloc 32 .seh_endprologue movl $65535, %edx movl $1, %ecx call _Z41__static_initialization_and_destruction_0ii nop addq $32, %rsp popq %rbp ret .seh_endproc .section .ctors,"w" .align 8 .quad _GLOBAL__sub_I_main .ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0" .def _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc; .scl 2; .type 32; .endef .def _ZNSolsEPFRSoS_E; .scl 2; .type 32; .endef .def system; .scl 2; .type 32; .endef .def _ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef .def _ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef .def atexit; .scl 2; .type 32; .endef .section .rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, "dr" .globl .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ .linkonce discard .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_: .quad _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ .section .rdata$.refptr._ZSt4cout, "dr" .globl .refptr._ZSt4cout .linkonce discard .refptr._ZSt4cout: .quad _ZSt4cout
3、匯編
g++ -c name.cpp / name.s
使用g++ -c b.s對匯編代碼進行匯編會生成相應的目標文件(b.o文件)
目標文件為二進制文件,由於尚未經過鏈接操作,所以無法直接運行。
4、鏈接
g++ b.o -o b.exe
將得到的b.o文件經過鏈接(一些函數和全局變量等)后便得到了可執行程序。
並不需要在g++添加任何選項,g++會在b.o的基礎上完成鏈接操作。
參考鏈接:http://c.biancheng.net/view/7960.html