【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的不 ...
随机推荐
- Image Based Lighting In UE3
"IBL"全称为"Image-based Lighint",是一种伪装全局光照的方法.使用该方法可以获得较好的视觉效果并且可以达到实时渲染的目的. 实现的方法之 ...
- JavaScript Map 实现
//定义map function Map() { this.container = {}; } //将key-value放入map中 Map.prototype.put = function(key, ...
- easyui datagrid动态设置行、列、单元格不允许编辑
Easyui datagrid 行编辑.列编辑.单元格编辑设置 功能: 动态对datagrid 进行行.列.单元格编辑进行设置不允许编辑. 禁用行编辑: 在编辑方法调用前,对选择的行进行判断,如果不允 ...
- unity3d控制主摄像头移动
这篇很水,因为就只有一行代码==: Camera.main.transform.Translate (Vector3.forward); 这行代码控制主摄像头向前移动,其它的如下: up:向上 dow ...
- sklearn中xgboost模块中plot_importance函数(特征重要性)
# -*- coding: utf-8 -*- """ ######################################################### ...
- Markdown进阶指南
数学公式编辑 Mac OS下建议使用Daum Equation Editor,按照MathType那样写公式,自动生成TeX代码 行内公式:用$...$包住Tex代码 行间公式:用$$..$$包住Te ...
- swiper动态加载数据滑动失效,ajax执行后swiper.js的效果消失问题
使用swiper.js做一些动效时,如果进行了ajax,并且重新把DOM写入到HTML代码中,会导致swiper.js的特效消失的问题.原因是ajax加载后,原先new 的Swiper对象,不认识新来 ...
- 3.selenium模块
本节内容: 介绍 安装 基本使用 选择器 等待元素被加载 元素交互操作 其他 项目练习 一.介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行Ja ...
- makefile之foreach函数
#$(foreach <var>,<list>,<text>) #把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再 ...
- lantin1
Latin1是ISO-8859-1的别名,有些环境下写作Latin-1. ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCI ...