【C语言天天练(二)】预处理
引言:
学C语言之初。一提到预处理,脑子里想到的就是#define的宏定义以及#include包括的头文件。后来随着对C的深入学习发现。预处理不止这些。比方条件编译、提前定义的宏等等。以下对此进行总结。
先给出预处理的定义:在编译程序之前,先由预处理器检查程序(因此称为预处理器),依据程序中使用的预处理器命令,预处理器用符号缩略语所代表的内容替换程序中的缩略语。
1. #define
最经常使用的预处理器命令就是define命令,该预处理器命令有三部分组成:#define本身、符号缩略语、替换列表(或称为主体)。
结构可写为:#define 宏 主体 当中宏部分不能有空格,仅仅能是数字、下划线、字母。但第一个字符不能使数字。
如:#define PX printf("x is %d.\n", x)
预处理器发现程序中的宏后,会用它的等价替换文件取代宏。假设该字符串中还包含宏。则继续替换这些宏。假设宏出如今双引號中,则不做替换。
假设在双引號中出现的宏前面有“#运算符”,则能够用宏參数创建字符串。如:
#define PSQR(X) printf("The square of X is %d.\n", ((X)*(X)))
PSQR(8) //等价于printf("The square of X is %d.\n", ((8)*(8)))。输出The square of X is 64.
#define PSQR(X) printf("The square of "#X" is %d.\n", ((X)*(X)))
PSQR(8) //等价于printf("The square of8 is %d.\n", ((8)*(8))),输出The square of8 is 64.
小结:引號中的字符中中的X被看作普通文本,而不是被看作一个可替换的语言符号。#符号用作一个预处理运算符,它能够把语言符号转化为字符串。
预处理器的粘合剂:##运算符。和上面的#运算符一样。##运算符能够用于类函数宏的替换部分。
##还能用于类对象宏的替换部分,把两个符号组合成单个语言符号,如:
#define XNAME(n) x##n
XNAME(4) //等价于x4
从宏的定义和使用能够看出,它与函数很相近,但宏与函数又有所不同,他们的选择实际上是时间和空间的权衡。
宏产生内联代码,也就是说在程序中产生语句。
假设使用宏20次,则会把20行代码插入程序中。假设使用函数20次,那么程序中仅仅有一份函数的语句拷贝,因此节省了空间。
还有一方面。程序的控制必须转移到函数中并随后返回调用程序。因此这比内联代码话费的时间多。
2.#include
预处理器发现#include指令后,就会寻找后跟的文件名称并把这个文件的内容包括到当前文件里。被包括文件的文本将替换源码文件里的#include指令。就像把被保护文件里的所有内容键入到源文件里的这个特定位置一样。
#include <name.h> // 文件放在尖括号里,搜索系统工作文件夹
#include “name.h” // 文件名称放在双引號中,搜索当前工作文件夹
#include "/dir1/dir2/name.h" // 搜索/dir1/dir2文件夹
头文件里一般包括的内容有:明显常量、宏函数、函数声明、结构体模板定义、类型定义
3. 其它指令
#undef指令取消前面的#define定义。
#if #ifdef #ifndef #else #elif #endif指令可用于选择什么情况下编译哪些代码。#line指令用于重置行和文件信息,#error指令用于给出错误消息。#param指令用于想编译器发出指示
4. 提前定义的宏:
__DATE__ : 进行预处理的日期
__FILE__ :代码当前源码文件名称的字符串文字
__LINE__ :代表当前源码文件里的行号的整数常量
__STDC__ :设置为1时。表示该实现遵循C标准
__TIME__ : 源文件编译时间
【C语言天天练(二)】预处理的更多相关文章
- 【C语言天天练(二四)】内存分配
引言: 对于C语言程序,了解它执行时在内存中是怎样分配的对于我们理解它的执行机制是很实用的.以下就总结一下C语言程序的一些内存分配知识. 一 一段C程序.编译连接后形成的可运行文件一般有代码段.数据段 ...
- 【C语言天天练(二一)】内联函数
引言:调用函数时,一般会由于建立调用.传递參数.跳转到函数代码并返回等花费掉一些时间,C语言的解决的方法是使用类函数宏.在C99中,还提出了第二种方法:内联函数. 内联 ...
- 【C语言天天练(二)】statickeyword
引言: statickeyword不仅能够修饰变量.并且能够修饰函数.了解它的使用方法,不仅对阅读别人的代码有帮助,也有助于自己写出更加健壮的程序. 使用方法: ...
- 【C语言天天练(二二)】位操作
C的位运算符 1.二进制反码或按位取反:~ ~(10011010) = (01100101). 假设val是一个unsigned char,~val不改名原来val的值. 2.位与:& 二进制 ...
- 【C语言天天练(十一)】深入理解指针
引言:在C语言中.指针的地位是不言而喻的,要想非常好的掌握C语言,掌握指针是必须的,这也是C语言不同于其它语言的地方. (一)指针的指针 样例: int i; int *pi;/*把pi初始化为指向变 ...
- 【C语言天天练(二三)】errno变量
引言: 在C编程中,errno是个必不可少的变量.特别是在网络编程中. 假设你没实用过errno,那仅仅能说明你的程序不够健壮. 为什么会使用errno呢?这是系统库设计中的一个无奈之举.他很多其它的 ...
- 【C语言天天练(九)】动态内存分配
引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化. ...
- 【C语言天天练(十五)】字符串输入函数fgets、gets和scanf
引言:假设想把一个字符串读到程序中.必须首先预留存储字符串的空间.然后使用输入函数来获取这个字符串. 读取字符串输入的第一件事是建立一个空间以存放读入的字符串. char *name; scanf(& ...
- 【C语言天天练(三)】typedef具体解释
引言: typedef能够看作type define的缩写,顾名思义就是类型定义,也就是说它仅仅是给已有的类型又一次定义了一个方便使用的别名.并没有产生新的数据类型. typedef与define的不 ...
随机推荐
- 基于Nginx实现一个自己的HTTP模块
/usr/local/nginx/conf/nginx.conf文件例如以下: #worker工作进程的用户及用户组 user weijl; #Nginx worker进程个数 worker_proc ...
- Hibernate继承类的实现
版权声明:本文为博主原创文章,如需转载请标注转载地址. 博客地址:http://www.cnblogs.com/caoyc/p/5603724.html 对于继承关系类的映射.比如在论坛中文章(Ar ...
- maven编译war包,pom中必须有的几个dependency
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> ...
- ISA95的抽象惯例
要想理解ISA95.而且应用到设计中去.就要理解ISA95背后的抽象模式,以下这个图是我依据我对ISA95的理解画出来的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkb ...
- (二)Solr——Solr界面介绍
1. Dashboard 仪表盘,显示了该Solr实例开始启动运行的时间.版本.系统资源.jvm等信息. 2. Logging Solr运行日志信息 3. Cloud Cloud即SolrCloud, ...
- 分享几款流行的Java框架
虽然Java一直被唱衰,但是直到现在Java软件开发也坚持霸主地位不动摇,毫无疑问,Java是目前最热门的编程语言之一,下面分享几个个人认为还不错的Java框架,以及各自的优缺点,希望能对大家有帮助. ...
- Linux命令-网络命令:last
last 统计linux系统所有用户的登录时间(多次登录信息)
- docker运行环境安装-后续步骤(二)
1.以非 root 用户身份管理 Docker [origalom@origalom ~]$ sudo groupadd docker # 创建docker用户组[origalom@origalom ...
- 参数数组(params)的用法
使用参数数组的注意事项: 1. 只能在一维数组上使用params关键字. 2. 不能重载一个只基于params关键字的方法.params关键字不构成方法的签名的一部分. 如: //编译时错误:重复访问 ...
- Spring事务的隔离级别
1. ISOLATION_DEFAULT: 这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别. 另外四个与 JDBC的隔离级别相对应: ...