【Linux】编译器-gcc/g++使用

Linux编译器-gcc/g++使用

gcc如何完成

  • 格式 gcc [选项] 要编译的文件 [选项] [目标文件]

背景知识

1. 预处理(进行宏替换)

在C语言中,预处理过程是在源代码被编译之前,在编译器进行编译的准备阶段进行的一系列操作。预处理器会根据预处理指令对源代码进行处理,并生成一个经过处理的新的代码文件,这个文件会成为编译器的输入。

预处理过程的主要目的是对源代码进行宏替换、文件包含、条件编译等操作,以生成编译器能够处理的标准C代码。

预处理过程主要包括以下步骤:

  1. 宏替换:将源代码中的宏定义进行替换。宏定义是一种预处理指令,用于定义常量、函数宏以及带有参数的宏。预处理器会将宏调用替换为宏定义的内容,并展开成新的代码。

  2. 文件包含:通过预处理指令#include将其他文件的内容包含到当前文件中。包含的文件可以是自定义的头文件,也可以是标准库的头文件。预处理器会将包含的文件插入到当前文件的相应位置。

  3. 条件编译:通过预处理指令#ifdef#ifndef#if等进行条件编译。这些指令可以根据条件判断是否编译某段代码。例如,根据定义的预处理宏来选择性地编译或排除代码块。

  4. 注释处理:预处理过程会移除源代码中的注释,以便生成更干净的代码供编译器处理。

  5. 其他处理:预处理器还可以进行一些其他的处理,例如标识符替换、字符串连接等。

总结
  • 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
  • 预处理指令是以#号开头的代码行。
  • 实例:
gcc –E hello.c –o hello.i
  • 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
  • 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序

2. 编译(生成汇编)

编译是将源代码转换为机器代码的过程。编译器负责将C语言源代码转化为可执行程序的二进制文件。

C语言编译的过程可以简化为以下几个步骤:

  1. 词法分析:编译器首先对源代码进行词法分析,将源代码分割成一个个的词法单元(token),例如关键字、标识符、运算符、常量等。词法分析的目的是将源代码转化为一个个独立的词法单元,方便后续的语法分析。

  2. 语法分析:编译器在进行语法分析时,会将词法单元组合成语法结构,例如表达式、语句、函数等。语法分析会根据语法规则检查代码的正确性和合法性,生成语法树(syntax
    tree)或者抽象语法树(abstract syntax tree),以方便后续的语义分析和代码生成。

  3. 语义分析:在语义分析阶段,编译器会对语法树进行进一步的处理和分析,检查语义错误和语义合法性。例如,类型检查、变量声明和作用域检查等。语义分析的主要目的是确保代码的正确性和一致性,为后续的代码生成做准备。

  4. 代码生成:在代码生成阶段,编译器会根据语法树和符号表(symbol table)生成机器代码。代码生成的目标是将高级语言的代码转化为特定机器平台的机器指令。这包括将C语言的变量、函数等映射到相应的机器寄存器或内存位置,生成适当的汇编指令和机器码。

  5. 优化:编译器还可以进行代码优化,通过对生成的机器代码进行优化算法的应用,改善程序的性能和效率。优化的目标是减少代码的执行时间、减小代码的空间占用,并提供更好的程序质量。

总结
  • 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
  • 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
  • 实例:
 gcc –S hello.i –o hello.s

3. 汇编(生成机器可识别代码)

  • 汇编生成的代码可以由汇编器(assembler)进行进一步处理,将汇编代码转化为机器码(二进制代码)。
  • 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
  • 读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
  • 实例:
gcc –c hello.s –o hello.o

4. 连接(生成可执行文件或库文件)

连接(linking)是将多个目标文件(object files)和库文件(library files)合并成一个可执行文件的过程。连接的过程主要包括以下几个步骤:

  1. 符号解析(Symbol resolution):连接器(linker)会解析每个目标文件中的符号引用(symbol references)和符号定义(symbol
    definitions)。符号是指变量、函数、类型等的名称。连接器会尝试找到每个符号的定义,如果找到了对应的定义,则将符号引用与定义关联起来。

  2. 地址重定位(Address relocation):在编译每个源文件时,生成的目标文件中的代码和数据使用的是相对地址(relative addresses)。连接器会将每个目标文件中的相对地址转化为最终的绝对地址(absolute
    addresses)。这样,当可执行文件运行时,代码和数据可以正确地被加载和访问。

  3. 符号合并(Symbol merging):在连接的过程中,如果多个目标文件中存在相同的符号定义,连接器会进行符号合并。这意味着多个目标文件共享同一个符号的定义,从而避免了多次定义相同符号的错误。

  4. 生成可执行文件(Executable generation):连接器最终会将所有解析过的目标文件和库文件合并成一个可执行文件。这个可执行文件包含了程序的所有代码、数据和符号定义。在运行时,操作系统加载可执行文件到内存中,并根据程序的入口点开始执行。

总结
  • 连接是将多个目标文件和库文件合并成一个可执行文件的过程。连接器通过符号解析、地址重定位和符号合并等步骤,将各个目标文件中的代码和数据组合成一个能够被操作系统加载和执行的可执行文件。

  • 实例:

gcc hello.o –o hello 

5.函数库 (一般分为静态库和动态库两种)。

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc hello.o –o hello
  • gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。

gcc选项

-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。

  • 46
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
arm-linux-gcc交叉编译器 4.3.2 part1 arm-linux-gcc-4.3.2.tgz.aa 需要与part2 arm-linux-gcc-4.3.2.tgz.ab 合并成arm-linux-gcc-4.3.2.tgz 。 版本4.3.2,用于Linux下的ARM开发。 安装方法: 0. cat arm-linux-gcc-4.3.2.tgz.aa arm-linux-gcc-4.3.2.tgz.ab > arm-linux-gcc-4.3.2.tgz 1. tar zxvf arm-linux-gcc-4.3.2.tgz -C/ 2. 编辑 ~/.bashrc ,加入 export PATH=$PATH:/usr/local/arm/4.3.2/bin 3. 验证安装 [root@xxxxx root]# arm-linux-gcc -v Using built-in specs. Target: arm-none-linux-gnueabi Configured with: /scratch/julian/lite-respin/linux/src/gcc-4.3/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion='Sourcery G++ Lite 2008q3-72' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/libc --with-gmp=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin Thread model: posix gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一岁就可帅-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值