上面已经介绍了 C 编译器的目标,其实在实现这个目标之前,是经历了很多阶段处理的,其中第一个阶段的处理,就是预处理。预处理的任务是做什么呢?在 LCC 里预处理主要是把所有包含的头文件和源程序生成一个中间文件,并且把所有宏展开,替换为真实的值。前面介绍的例子源程序,经过预处理后,就会生成下面的代码,如下:
#line 1 "hello.c"
#line 1 "include/stdio.h"
typedef unsigned int size_t;
typedef unsigned short wchar_t;
typedef wchar_t wint_t;
typedef wchar_t wctype_t;
typedef char *    va_list;
#line 39 "include/stdio.h"
struct _iobuf {
 char *_ptr;
 int   _cnt;
 char *_base;
 int   _flag;
 int   _file;
 int   _charbuf;
 int   _bufsiz;
 char *_tmpfname;
 };
typedef struct _iobuf FILE;
extern FILE *_iob;
typedef long fpos_t;
extern FILE (*__imp__iob)[];
int _filbuf(FILE *);
int flsbuf(int, FILE *);
FILE * _fsopen(const char *, const char *, int);
void clearerr(FILE *);
int fclose(FILE *);
int _fcloseall(void);
FILE * fdopen(int, const char *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *);
int fgetc(FILE *);
wchar_t fgetwc(FILE *);
wchar_t getwc(FILE *);
int _fgetchar(void);
int fgetpos(FILE *, fpos_t *);
char * fgets(char *, int, FILE *);
int fileno(FILE *);
int _flushall(void);
FILE * fopen(const char *, const char *);
int fprintf(FILE *, const char *, ...);
int xfprintf(FILE *,const char *,...);
int fputc(int, FILE *);
int _fputchar(int);
int fputs(const char *, FILE *);
size_t fread(void *, size_t, size_t, FILE *);
FILE * freopen(const char *, const char *, FILE *);
int fscanf(FILE *, const char *, ...);
int xfscanf(FILE *,const char *,...);
int fsetpos(FILE *, const fpos_t *);
int fseek(FILE *, long, int);
long ftell(FILE *);
size_t fwrite(const void *, size_t, size_t, FILE *);
int getc(FILE *);
int getchar(void);
char * gets(char *);
int getw(FILE *);
int _pclose(FILE *);
FILE * popen(const char *, const char *);
int printf(const char *, ...);
int xprintf(const char *,...);
int dprintf(const char *, ...);
int putc(int, FILE *);
int putchar(int);
int puts(const char *);
int _putw(int, FILE *);
int remove(const char *);
int rename(const char *,const char *);
void rewind(FILE *);
int _rmtmp(void);
int scanf(const char *, ...);
int xscanf(const char *,...);
void setbuf(FILE *, char *);
int setvbuf(FILE *, char *, int, size_t);
int _snprintf(char *, size_t, const char *, ...);
int sprintf(char *, const char *, ...);
int xsprintf(char *, const char *, ...);
int snprintf(char *,size_t,const char *,...);
int xsnprintf(char *,size_t,const char *,...);
int sscanf(const char *, const char *, ...);
int xsscanf(const char *,const char *,...);
char * _tempnam(char *, char *);
FILE * tmpfile(void);
char * tmpnam(char *);
char *tempnam(char *,char *);
int ungetc(int, FILE *);
int _unlink(const char *);
int vfprintf(FILE *, const char *, va_list);
int vprintf(const char *, va_list);
int _vsnprintf(char *, size_t, const char *, va_list);
int _vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
int vsnprintf(char *,size_t,const char *,va_list);
int xvsnprintf(char *,size_t,const char *,va_list);
int xvsnprintf(char *,size_t,const char *,va_list);
int vsprintf(char *, const char *, va_list);
int xvsprintf(char *, const char *, va_list);
void perror(const char *);
void _wperror(const wchar_t *);
#line 2 "hello.c"
int main(void)
{
 int nTest1 = 1;
 int nTest2 = 2;
 int nTest3;
 int i;
 nTest3 = nTest1 + nTest2;
 printf("nTest3 = %d/r/n",nTest3);
 for (i = 0; i < 5; i++)
 {
       printf("%d/r/n",nTest3+i);
 }
 printf("00:30:28"" ""Apr 07 2007""/r/nhello world/n");
 return 0;
}
现在就来分析一下经过预处理的中间文件。
#line 1 "hello.c"
这行告诉编译器要编译的源文件名称和行号。这里是 hello.c 的第一行。
#line 1 "include/stdio.h"
在 hello.c 的第一行里包含了一个头文件 include/stdio.h ,而这个头文件源程序紧跟着后面,直到 #line 2 "hello.c" 行前,都是包含的头文件源程序。在那行的后面才是 hello.c 的源程序,可以看到在 main 函数里的宏定义也被替换掉了。如下:
printf("00:30:28"" ""Apr 07 2007""/r/nhello world/n");
预处理把宏定义 __TIME__ 变成了 "00:30:28" 字符串,把宏定义 __DATE__ 变成了 "Apr 07 2007" 。这两个宏定义生成的字符串跟编译时间相关,其实就是把当前编译的时间生成字符放到相应的位置。
上面的中间源程序是 LCC 预处理生成样子,没有删除任何一行,即使是空行也没有删除一行。其实在 C 里,还有使用 #define 定义的宏定义,也会替换掉的。因此,在宏定义处理里,没有复杂的计算,只是字符串的替换。在这里没有介绍完整的预处理代码,因为把主要精力放到 C 编译器去。

C 编译器就是接收上面这样的中间文件,进行编译处理的。

LCC编译器的源程序分析(2)LCC编译器的预处理相关推荐

  1. 【开发环境】Ubuntu 中使用 VSCode 开发 C/C++ ④ ( 创建 tasks.json 编译器构建配置文件 | tasks.json 编译器构建配置文件分析 )

    文章目录 一.创建 tasks.json 编译器构建配置文件 二.tasks.json 编译器构建配置文件分析 可以参考官方提供的文档 : https://code.visualstudio.com/ ...

  2. i++和++i作为参数时的编译器处理方式分析

    这是一个很简单的程序 void main() { int i=8; printf("%d,%d,%d,%d\n", ++i, --i, i++, i--); } 在这里我使用了VS ...

  3. GCC编译器优化选项分析及具体优化了什么

    问题 在使用gcc作为编译器.在设定编译条件时,在debug模式下生成的程序正常,但是在release模式下往往会出现很多种预料之外的结果,尤其在嵌入式环境中,程序在板子上运行的时候,问题就愈发明显. ...

  4. 编译器设计(一)——简单介绍一个编译器的结构

    一个编译器的结构 一.语言处理器 二.编译器的结构 三.词法分析 四.语法分析 五.语义分析 六.中间代码生成 七.机器无关代码代码优化 一.语言处理器 计算机很笨,只能认识0和1,而人呢,脑子的存储 ...

  5. c语言编译器 代码优化,c编译器高级篇!!搞定c编译器优化

    对于c编译器,想必大家也有所了解,3款主流c编译器也是活跃在不同人群的PC上.网络上很多文章都止步于对c编译器的介绍,并未探索c编译器更加深层次的内容.而在本文中,将涉及c编译器的高级部分--c编译器 ...

  6. 编译器不识别stm指令_编译器简介

    编译器是将"一种语言(高级语言)"翻译为"另一种语言(低级语言)"的程序. 编译器能够识别代码中的词汇.句子以及各种特定的格式,并将他们转换成计算机能够识别的二 ...

  7. c语言编译器a安卓,c语言编译器手机版下载-c语言编译器appv7.1 安卓版 - 极光下载站...

    c语言编译器app是一个强大的手机编程app,用户可以使用这个软件在手机上进行编程,通过编译c语言代码来查看程序.软件编译效果和电脑端完全一样,用户不必担心有其他的问题.软件不仅体积小而且运行速度快, ...

  8. Matlab 2017b错误使用 mex 未找到支持的编译器或 SDK。您可以安装免费提供的 MinGW-w64 C/C++ 编译器;请参阅安装 MinGW-w64 编译器

    Matlab 2017b错误使用 mex 未找到支持的编译器或 SDK.您可以安装免费提供的 MinGW-w64 C/C++ 编译器:请参阅安装 MinGW-w64 编译器. 1.首先打开matlab ...

  9. lex与yacc程序学习(3)——yacc源程序的结构yacc编译器的实践

    yacc源程序的结构 声明部分 %% 翻译规则 %% 辅助函数 声明部分和辅助函数与lex相同. 翻译规则:语法规则+相应的语义动作 下面是一个完整的yacc程序代码: %{#include<s ...

最新文章

  1. C++ 向量(vector) 的使用
  2. Python使用shape计算矩阵的行和列
  3. http://wenku.baidu.com/view/63e7b8270066f5335a812142.html
  4. SAP以创新提升极限帆船赛
  5. android x86一键安装,安卓
  6. 配置Vlan访问控制
  7. RMS 相关下载链接
  8. 启动时指定需要绑定的网卡_为什么小型汽油机在启动时需要拉风门,而汽车却不用?...
  9. 怎么把桌面计算机放到快速启动栏,怎么把桌面图标放到快速启动栏
  10. 杭电计算机学院大学生程序设计竞赛(2015’11)
  11. 【BZOJ3156】防御准备,斜率优化DP
  12. Hibernate的transaction嵌套
  13. winfrom datagridview中DataGridViewTextBoxColumn的联动处理
  14. 力扣-119. 杨辉三角 II
  15. java程序员选择多个offer时需要看重哪些?_27 道阿里巴巴 Java 面试题,你会几道?...
  16. vb从入门到精通_益智 | 用VB编程开发的围棋游戏!
  17. CMOS 集成电路设计手册 (基础篇)--学习笔记 第二章
  18. 《GPU编程与CG语言之阳春白雪下里巴人》阅读笔记 第五章+第六章
  19. js-es6知识汇总(1) 原型与原型链
  20. 报错:org.springframework.security.web.firewall.RequestRejectedException: The request was not ......

热门文章

  1. 文本转为mardown表格或者是excel在线工具
  2. Java实现多人聊天室
  3. Data Binding Library
  4. android 仿Boss直聘消息界面
  5. python学习——IO编程——文件读写
  6. FPGA:计算滑动求和----信号检测计算信号功率
  7. 【涵子来信Linux百宝书】——Linux实体机简约安装教程
  8. mysql dialect配置_一步一步升级配置14: Mysql数据库,hibernate.dialect 使用MySQL5Dialect 替代 MySQLDialect...
  9. UEFI+GPT与Legacy+MBR的区别
  10. 操作系统:BIOS+MBR和UEFI+GPT