C语言编译过程

C语言编译过程

最近准备秋招,想把知识体系整理下,可以更好的应对面试中的问题。

预处理

命令:gcc -E add.c -o add.i
C 预处理器相当于一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理。或者说是扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器,这一过程中不会进行语法解析。
可以打开.i文件看一下,多出来很多行,但还是c语言的东西。

宏定义指令

#define指令

语法:

#define	NUM 10
int arrar[NUM];

好处:

  1. 习惯上使用大写字母来定义宏,使用方便。
  2. 易读性高。
  3. 容易修改。

注意:宏展开需要注意运算符优先级的问题。

带参数的#define指令(带参宏)

带参宏的使用与函数类似

#define RGB888(r, g, b) (((r&0xff) << 16) | ((g&0xff) << 8) | (b & 0xff))

使用时同样需要注意优先级问题,使用时最好加上括号。

带参宏和带参函数的区别

宏展开仅仅是字符串的替换,不会对表达式进行计算;宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存。而函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。
宏没有返回值,函数可以有返回值

#运算符

也被称为字符串化运算符,即

#define STRING(n) "123"#n
int main()
{
		printf("%s\n", STRING(567));
       	return 0;
}
//输出:123567
##运算符(很少用)

##运算符用于把参数连接到一起。预处理程序把出现在##两侧的参数合并成一个符号。

#define NUM(a,b,c) a##b##c
#define STR(a,b,c) a##b##c
int main()
{
      printf("%d\n",NUM(1,2,3));
      printf("%s\n",STR("aa","bb","cc"));
      return 0;
}
/*
输出:
	123
   aabbcc
*/

条件编译

贴上本人常用的条件编译。

//1.防止头文件被重复包含出现意想不到的问题
#ifndef __HEAD_H__
#define __HEAD_H__

#endif

//2.条件编译屏蔽代码,在调试中常用
#if 0

#endif

//3.代码条件定义,来自linux内核
  #ifdef KEY_DEBUGGING    
          unsigned                magic;    
  #define KEY_DEBUG_MAGIC         0x18273645u    
  #define KEY_DEBUG_MAGIC_X       0xf8e9dacbu    
  #endif

头文件包含

#include <stdio.h>
#include "head.h"

//<> 告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件
//"" 告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头
//文件,如果找不到,再搜索编译器自带的头文件

编译

命令:gcc -S add.i -o add.s
将经过预处理之后的程序转换成特定汇编代码的过程,生成的.s文件是汇编文件

汇编

命令:gcc -c add.s -o a.o
将上一步的汇编代码转换成机器码,生成的.o文件是二进制文件

链接

命令:gcc add.o -c add
将所有二进制形式的目标文件和系统组件组合成一个可执行文件。

面试预处理可能会问一些,其余的知道就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值