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日完成。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“g++及make/makefile的编译过程介绍及C标准的发展历程” 的相关文章