当前位置: 首页 > news >正文

gcc预处理、编译、链接简述

 

C语言的编译过程主要分成3个阶段:

1:预处理

2:编译

3:链接

 

1 预处理

       该阶段有两个工作,一是将#define 给扩展开来,二是通过#include将.h文件加入到该代码中。

代码中所有用到define一样字符串的位置通过define的规则给一一替换。前一个#define 会影响后一个#define,但是代码中常量字符串不会被替换。

例子:

#define I 6

#define J I*5  //I会被替换成6

 

int main()

{

       int i=J;        //J会被替换成6*5

       char a[30]="dgJ";  //J不会被替换

return 0

}

 

#define 的一些高级运用:

#define MAX(x,y) ((x)>(y)? (x):(y))

对于MAX(5,6)将被替换为((5)>(6)? (5):(6))

但是对于MAX(f(5),f(6))将被替换为:

((f(5))>(f(6))? (f(5)):(f(6)))

函数被多调用,如果函数本身很复杂则得不偿失。

所以可以写成

#define MAX(x,y) ({typeof(x) _x=x;\

                              typeof(y) _y=y;\

                              _x>_y? _x:_y;})

 

       一个块的值(即大括号{})是最后一个表达式的值。

 

#和##在宏定义中的作用

       #define A(a,b) a##b //连接a和b

       #define B(r) #r  //将r变为字符串”r”

 

#include的具体处理

#include的头文件会被依次加入代码中。

如果有递归定义的#include,以前的实现中将无限递归加载,现在的大多实现中解决了这个问题,但是还是最好自己用#ifndef __xxx__的方式来限定一个.h只能被调一次。

#ifndef __XXXXH__

#define __XXXXH__

...

...

...

#endif

 

2 编译和链接

       具体做了什么,自己百度。在此只是说一个很有意思的现象。在链接阶段,即使你在代码头部没有包含标准库的头文件,但是代码中调用了标准库函数,实际链接的过程中,会准确定位到该函数,程序将正确执行。

       看例子就懂了:

#include <stdio.h>

 

int strlen(const char *,int);

 

int main()

{

    int i;

    i=strlen("sdf",5);

    printf("%d\n",i);

    return 0;

}

 

如果没有加int strlen(const char *,int);会报strlen没有声明的错误,所以要加上。

实际上,我没有实现strlen函数,也没有加string.h的头文件,但是程序运行正常(将会调用标准库的strlen())。因为编译阶段,只是简单的一个语法检查,它认为strlen(“sdf”,5)的调用没有问题,因为我在前面声明了这个函数。链接阶段,会搜整个标准库一遍,所以strlen将调用标准库string.h中的strlen()函数。

真实执行中,参数5入栈、参数char *入栈,然后调用标准库string.h里的strlen(const char *)。但是标准库的strlen()明明只有一个参数,会出现执行错误么?答案是不会,因为char *无论是哪种相对栈指针的偏移是一致的,strlen()函数将能正确访问到char *变量,int参数5虽然入栈,但是函数中没有访问它。这一块具体可以看C语言内存管理中的栈区加深理解。

 

转载于:https://www.cnblogs.com/zebfff/p/5110189.html

相关文章:

  • 《jQuery基础教程:第2版》PDF
  • 《C#入门经典》(第4版)
  • Python批量删除指定目录下的指定类型的文件
  • Xcode-程序开发设计-02九宫格
  • C语言程序设计(第二版) 谭浩强下载- 免费电子书|电子书下载
  • 深入理解数据库磁盘存储(Disk Storage)
  • Android 程序员指南 PDF下载
  • nodejs review-04
  • 扩展方法
  • Readiris Pro 12 中文版- 专业OCR扫描软件
  • 如何设计好类的接口
  • 最好的FLV视频下载器 维棠 (支持优酷视频下载、土豆视频下载等)
  • [bzoj1901]: Zju2112 Dynamic Rankings
  • 好玩的软件 Aura 模拟自然界中的音效,让你置身大自然。
  • Intent基本使用
  • CSS 三角实现
  • css属性的继承、初识值、计算值、当前值、应用值
  • ES6 ...操作符
  • Golang-长连接-状态推送
  • HTML-表单
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Magento 1.x 中文订单打印乱码
  • mysql 数据库四种事务隔离级别
  • Redis中的lru算法实现
  • 从0到1:PostCSS 插件开发最佳实践
  • 工作中总结前端开发流程--vue项目
  • 前端面试题总结
  • 算法-图和图算法
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 微信小程序--------语音识别(前端自己也能玩)
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • !!Dom4j 学习笔记
  • $ git push -u origin master 推送到远程库出错
  • ${factoryList }后面有空格不影响
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (1)Android开发优化---------UI优化
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (pytorch进阶之路)扩散概率模型
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (二)JAVA使用POI操作excel
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (附源码)计算机毕业设计大学生兼职系统
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (七)理解angular中的module和injector,即依赖注入
  • (算法)N皇后问题
  • (算法设计与分析)第一章算法概述-习题
  • (转)详解PHP处理密码的几种方式
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .net core使用RPC方式进行高效的HTTP服务访问