程序诞生的第一步--预处理

程序诞生的第一步——预处理

程序在编译前要进行预处理,这一步被为预处理阶段,主要是进行一些文本性的操作,比如宏的替换,插入一些由#include指令所包含的一些文件的内容,以及处理一些条件编译的东西。下面介绍预处理的主要部分宏及其相关知识和一些标准中的命令。

首先标准中确定的一些预定义符号:

__FILE__              进行编译的源文件名

__LINE__              文件当前的行号

__DATE__            文件被编译的日期

__TIME__             文件被编译的时间

__STDC__            如果编译遵循ANSI C其值就为1

#define 的用法

#define    NAME       EXP

在预处理阶段编译器就会把文件中所有的NAME全部替换成EXP(可以是字符,也可以是表达式)只要使用#define指令就可以替换任意的文本到文件中。NAME和EXP都是自己可以定义的。

如果一行写不下,可以在这一行的最后加上字符 \ 下一行接着写,编译器会认为这是一个东西。

例如:

#define PRINT     printf("this file is %d:" \

"x=%d,y=%d,z=%d\

__FILE__,__LINE__,\

x,y,z)

像这样的生命都是合法的,其打印值也是我们所期望的打印值。

宏:

其实#define指令并不能与宏相等,这个指令包含一个规定就是宏这种用法,

如果一个宏带参数那么参数列表应当紧挨着宏名,并且后边宏的参数都应当带上括号,防止由于运算符号优先级带来的一系列问题。

举个例子:

#define<stdio.h>

#define   SUM(x)   x*x

int main()

{

int a=5;

int b;

b=SUM(a+1);

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

return 0;

}

此时打印出来的东西到底是什么?有人可能会回答36,其实博主在学习C语言的过程中也回答过36这个答案,但其实正确的答案是11.请考虑下这个宏到底是如何替换的。其实是a+1*a+1,按照C语言的运算符优先级乘法运算高于加法运算(无括号情况下)这个值就是11,这和我们的想法相差甚远,这就是为什么在声明带参数的宏时一定要注意带括号的问题。

#define的替换:

在使用宏进行替换操作时要注意其替换过程:

1.在调用宏时,首先对参数进行检查,看看是否包含了任何宏定义过的符号,如果是他们首先被替换。

2.替换文本随后被插入到程序中宏明的地方,此处是完全的替换。

3.最后再对文本进行扫描,看看它是否包含了任何由#define定义的符号,如果有重复上面的过程。

另外:宏也可以应用与字符串

宏与函数:

首先说明几个其他相关知识点:

宏其实有时候有副作用,不要在宏中出现X++这种语句,它会给程序带来不可预知的恶劣影响。

宏命名的约定:虽然宏明可以自定义,但是请用大写命名吧这样方便自己也方便日后维护程序的人,我们要有专业精神。

现在来说宏与函数的区别于优劣性:

宏:

宏每次都要插入到程序中,有可能导致程序的代码量会变得非常的大,但是宏的执行速度非常快(毕竟不再运行阶段处理宏),宏在其上下文环境中应当尽可能的加上括号防止因为运算符优先级产生问题,对与宏的参数求值,具有副作用的宏会带来不良影响,宏与类型无关只要对参数的操作合法,它可以是任意类型。宏不能传递类型名,不能递归。

函数:

函数每次调用都要执行相同的代码段,再返回值是会有额外的开销,参数的副作用没有影响,参数的值对于类型有严格的要求,总体运行较慢(毕竟是在运行阶段调用)。

#undef  移除一个已经声明过得宏。

#error text of error   message   定义一个表示错误地宏

条件编译:

#define   NAME    1

#if    NAME

EXP

#endif

如果已经定义了某个宏比如NAME,那么编译器会自动的对其进行运算,如果为真则编译EXP后结束,如果为假那么就跳过EXP。

这种判断是可以嵌套的还有#elif ,这其实很像if-else-if语句,其实在意思上都是差不多的。

#if NAME

EXP

#elif  NAME1

EXP2

#elif  NAME2

EXP3

#else

EXP4

#endif

都是在前一个判断为假的时候才编译后一个语句的。

对于条件编还有最后一个问题:

就是是否被定义的问题,要知道在头文件中不能对一个宏进行反复的声明,但是有时候却会出现这样的问题;

解决方法;

#ifndef  NAME

#define   NAME

这两句就是如果没有定义过NAME,那么就定义一个NAME,这样可以有效解决反复声明同一个宏的问题。

函数库文件与本地文件的问题;

一般默认#include<NAME.h>是系统的函数库,#include"NAME.h"是用户本地的文件,根据编译器的不同可以去设置其查找范围,其实没有功能上的区别就算你用尖括号包含了本地的文件,编译器在库中找不到时会自动扫描当前的目录来找到它,有强迫症的可以去自行百度看看怎么改这个东东。

时间: 2024-10-01 12:19:41

程序诞生的第一步--预处理的相关文章

配置环境是程序员的第一步 -- Windows 10 下 MySQL 安装

MySQL 作为最典型的关系型数据库管理系统,由于其体积小.速度快.总体拥有成本低,尤其是其开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库.MySQL 社区版的功能也足够我们的日常使用.MySQL 的安装过程不是很难,但是有几个点还是要需要注意的.下面,我将以 Windows 10 为例,讲一下 MySQL 社区版的安装. 首先,我们进入 MySQL 官网,下载 MySQL 社区版.https://dev.mysql.com/downloads/mysql/ 这里,我们

Linux下的第一步——进度条(gcc&Makefile)

相信大家在初步学习C/C++的时候都写过"hello world"的代码.在学习了C/C++之后进入Linux系统的学习我们不用再从"hello world"这种入门级程序开始了,毕竟已经有了几年的小经验,但是重新开始在一个新的系统下编写代码,特别是对于Linux中庞杂的指令是需要一个熟悉与练习的过程的.进度条的小程序对于我们熟悉指令,练习VIM下代码的编辑以及gcc和Makefile等工具的使用都是很有帮助的. VIM之前已经介绍过了,就不做过多赘述,今天利用这个

第三 章、面向对象 第一步部分

一.类与对象的基本概念 类:抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法): 对象:是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性区分不同的对象. 类与对象的区别:类是对象的模板,对象是类的实例,类只有通过对象才可以使用,开发中应该先产生类,再产生对象.类不能直接使用,方法可以直接使用. 二.类与对象的定义 1.类的定义: 在JAVA中定义类,可以使用class关键字完成, 语法为: 1 class 类名称{ 2 属性(变量): 3 行为(方

核心思想:用技术创造价值的第一步:定义价值点,也就是找到杠杆的支点(陈天桥是典范)

杠杆 技术本就是一种杠杆. 曾经,技术的草莽时期,是一个英雄辈出的年代.两个人可以创造 Unix,C 语言,一个人也可以发明 Linux,也可以写出 Foxmail.掌握了技术,就可能创造历史,那时技术的杠杆很高. 如今,是技术的成熟时期,个体英雄少了,更多是一种团队和集团军作战的时代.如果你是技术的绝世高手(精的极致),那你需要找到一支契合你技能的场景与队伍,加入进去.此时个人的技术杠杆也许不像曾经那么高 —— 能创造历史,但也许你们这个队伍还是有机会能创造历史. 前几年,Facebook 曾

Git 系列——第一步安装 Git

之前也没有用过什么版本控制的工具,唯一用过的就是 SVN 了,不过也只是简单的使用而已,比如写好代码就签入,没了?是的,没了. 于是接触到了 Git 这个分布式版本控制软件,接下来就让我们好好学习,天天向上吧. 第一步当然需要安装 Git 了,其实这一步本来没什么可说的,毕竟程序员哪有不会装软件的...说的也是.不过还是打算一步一步来. 由于我使用的是 Windows 操作系统,所以我下载的是 Windows 版,下载 Windows 版 Git.其他操作系统的如:Linux.Mac,可以参考这

极速微信小程序开发,第一天

收到xx平台的合同确认的短信后,下午把手上的事情理完后.Get一项新技能之前和微信相关的单都是转出去给人家做,许久没有打代码了,前端的技术也忘的差不多了.还好现在项目选型的时候,通过讨论最终明确下来,采用时下流行的框架.如Vue,Angural,后端采用了go语言 一直认为微信就是js调用接口的玩意,使用微信封装好的公共方法来快速开发微信网站及小程序.看官们不要相信我的片面之词 还是从先从微信官方指引入手,第一感觉内容很简洁,配上了图,理解起来就更方便了. 今天我主要回顾一下,为了快速消化这个单

初学者的第一步。

---恢复内容开始--- 初学小程序: int i; gotoxy(40,13); printf("lingzhipeng"); gotoxy(40,12); printf("1-212"); gotoxy(40,11); printf("TEL:13217935482"); gotoxy(30,15); printf("***********************************"); gotoxy(30,8);

Scala的第一步

第一步:学习使用Scala解释器 开始Scala最简单的方法是使用Scala解释器,它是一个编写Scala表达式和程序的交互式“shell”.在使用Scala之前需要安装Scala,可以参考 First Steps to Scala 内容. 你可以在命令提示符里输入scala使用它: $ scala Welcome to Scala version 2.9.2. Type in expressions to have them evaluated. Type :help for more inf

python012 Python3 编程第一步

Python3 编程第一步在前面的教程中我们已经学习了一些 Python3 的基本语法知识,下面我们尝试来写一个斐波纳契数列.实例如下: #!/usr/bin/python3 # Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 while b < 10: print(b) a, b = b, a+b 执行以上程序,输出结果为: 1 1 2 3 5 8 这个例子介绍了几个新特征.第一行包含了一个复合赋值:变量 a 和 b 同时得到新值 0