g++及make/makefile的编译过程介绍及C标准的发展历程
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
g++/make的编译过程
c++的程序编译的过程如下
1.预编译
->2.编译
->3.汇编
->4.链接
以个Test.cpp
为例说明整个编译过程
Test.cpp
文件如下
#include <iostream>
#define MAX_NUM 10
// 定义宏
int main() {
// 输出Hello world
std::cout<<"Hello world!"<<std::endl;
// 输出Max+n
int n = 100;
std::cout<<"MAX_NUM+n:"<<MAX_NUM+n<<std::endl;
return 0;
}
1预编译
宏的替换还有注释的消除还有找到相关的库文件
g++ -E Test.cpp > Test.i
只做预处理生成一个Test.i
的文件该文件多了很多内容我们省略前面1万+行
只看最下面对我们的写的源码做了什么处理
Test.i
内容如下
int main() {
std::cout<<"Hello world!"<<std::endl;
int n = 100;
std::cout<<"MAX_NUM+n:"<<10 +n<<std::endl;
return 0;
}
这就是预处理做的我们能理解的事其他的有空自己再慢慢深挖。
2编译
将预处理后的文件转换为汇编文件里面为汇编指令
g++ -S Test.i
当然也可以直接将源代码cpp处理 g++ -S Test.cpp
两者编译后的输出结果一模一样
编译后将得到一个Test.s
的文件前面0行开始截取部分内容如下
.file "Test.cpp"
.text
.section .rodata
.type _ZStL19piecewise_construct, @object
.size _ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
.zero 1
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.LC0:
.string "Hello world!"
.LC1:
.string "MAX_NUM+n:"
.text
.globl main
.type main, @function
main:
.LFB1522:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
leaq .LC0(%rip), %rsi
leaq _ZSt4cout(%rip), %rdi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
movq %rax, %rdx
movq _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
movq %rax, %rsi
movq %rdx, %rdi
call _ZNSolsEPFRSoS_E@PLT
movl $100, -4(%rbp)
leaq .LC1(%rip), %rsi
leaq _ZSt4cout(%rip), %rdi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
movq %rax, %rdx
movl -4(%rbp), %eax
addl $10, %eax
movl %eax, %esi
movq %rdx, %rdi
call _ZNSolsEi@PLT
movq %rax, %rdx
movq _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
movq %rax, %rsi
movq %rdx, %rdi
call _ZNSolsEPFRSoS_E@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
...
显然上面的是机器无关的汇编指令
3汇编
将汇编文件转为目标文件
g++ -c Test.s # 当然也可以直接使用`g++ -c Test.cpp`从源文件直接输出
汇编执行后将生成Test.o
的目标文件二进制文件
4链接
将目标文件和库文件整合为一个可执行文件
g++ Test.o -L usr/include/iostream
-L后为库文件目录
命令执行后将生成一个a.out
我们可以运行一下该文件前面的代码正常运行如下所示
$ ./a.out
Hello world!
MAX_NUM+n:110
使用-o可以为可执行文件命名
g++ Test.o -o Test -L usr/include/iostream
# 同理可以直接对源码输出`g++ Test.cpp -o Test -L usr/include/iosream`
执行后将输出Test
的可执行文件
5一步到位编译
# 直接编译
g++ Test.cpp -o Test
# 执行结果
./Test
Hello world!
MAX_NUM+n:110
直接输出Test
可执行文件
g++常用的参数
-c 生成.o目标文件
-o可执行文件命名
-shared 指定生成动态链接库
-static 指定生成静态链接库
-L 要链接的库所在目录
-l 指定链接时需要的动态库隐含命名规则即在前加lib在后加.a或.so确定库文件名
-std 设置C语言版本 g++ -std=c11 Test.cpp -o Test
C语言版本的发展历程简介
如何查看编译支持C语言标准
先查看一下gcc
的版本
$ gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
版本为9.4.0
可以去官网查看9.4.0
支持那些C的标准或者直接用下面的命令
$ man gcc
-std=
Determine the language standard. This option is currently only supported when compiling C or C++.
The compiler can accept several base standards, such as c90 or c++98, and GNU dialects of those standards, such as gnu90 or gnu++98. When a base standard is specified, the compiler
accepts all programs following that standard plus those using GNU extensions that do not contradict it. For example, -std=c90 turns off certain features of GCC that are incompatible
with ISO C90, such as the "asm" and "typeof" keywords, but not other GNU extensions that do not have a meaning in ISO C90, such as omitting the middle term of a "?:" expression. On the
other hand, when a GNU dialect of a standard is specified, all features supported by the compiler are enabled, even when those features change the meaning of the base standard. As a
result, some strict-conforming programs may be rejected. The particular standard is used by -Wpedantic to identify which features are GNU extensions given that version of the standard.
For example -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not.
A value for this option must be provided; possible values are
c90
c89
iso9899:1990
Support all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as -ansi for C code.
iso9899:199409
ISO C90 as modified in amendment 1.
c99
c9x
iso9899:1999
iso9899:199x
ISO C99. This standard is substantially completely supported, modulo bugs and floating-point issues (mainly but not entirely relating to optional C99 features from Annexes F and G).
See <http://gcc.gnu.org/c99status.html> for more information. The names c9x and iso9899:199x are deprecated.
c11
c1x
iso9899:2011
ISO C11, the 2011 revision of the ISO C standard. This standard is substantially completely supported, modulo bugs, floating-point issues (mainly but not entirely relating to
optional C11 features from Annexes F and G) and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability). The name c1x is deprecated.
c17
c18
iso9899:2017
iso9899:2018
ISO C17, the 2017 revision of the ISO C standard (published in 2018). This standard is same as C11 except for corrections of defects (all of which are also applied with -std=c11)
and a new value of "__STDC_VERSION__", and so is supported to the same extent as C11.
c2x The next version of the ISO C standard, still under development. The support for this version is experimental and incomplete.
上面存在C11
C17
C18
说明都支持这些C语言版本
C语言版本的发展历程
C89之前并没有统一C标准规范
-
C89
考虑到标准化的重要ANSIAmerican National Standards Institute制定了第一个 C 标准在1989年被正式采用American National Standard X3.159-1989故称为 C89也称为 ANSI C。
该标准随后被 ISO 采纳成为国际标准ISO/IEC 9899:1990。 -
C95
这是对 C89 的一个修订和扩充称为“C89 with Amendment 1”或 C95严格说来并不是一个真正的标准。 -
C99
1999年在做了一些必要的修正和完善后ISO 发布了新的 C 语言标准命名为 ISO/IEC 9899:1999简称“C99” -
C11
2007 年C语言标准委员会又重新开始修订C语言到了2011 年
正式发布了 ISO/IEC 9899:2011简称为 C11 标准。
C11 标准新引入的特征尽管没 C99 相对 C90 引入的那么多但是这些也都十分有用比如字节对齐说明符、泛型机制generic selection、对多线程的支持、静态断言、原子操作以及对 Unicode 的支持。 -
C17
C17也被称为为 C18是于2018年6月发布
的 ISO/IEC 9899:2018 的非正式名称也是目前截止到2020年6月为止最新的 C语言编程标准被用来替代 C11 标准。
C17 没有引入新的语言特性只对 C11 进行了补充和修正。 -
C2x
C 2x下一个版本的 C 标准预计将于2022年12月1日
完成。