编写一个C程序,第一个步骤称为预处理,预处理在代码编译之前,进行一些文本性质的操作,删除注释、插入被include的文件、定义替换由#define定义的符号,以及确定代码的部分内容是否应该按照条件编译

共有五个预处理指令:

预定义指令:define

条件编译:#if, #elif,#else,#endif,#ifdef,#ifndef

文件包含#include

编译错误:#error指令

#progma指令

一、预定义指令:define

#define name stuff

define为数值命名一个符号,每当有name出现时,就会被替换成stuff。多行命名可以用\分隔开每行。define机制包括一个规定,允许把参数替换到文本中,称为宏(macro).

#define name(paramater-list) stuff

其中parameter-list是由逗号分隔的符号列表,可以出现在stuff中。name和左括号直接不可以有空格,不然会被当做stuff一部分处理。

#define MUT(x, y) x *y

如果MUT(3+1, 1+2)会被展开成:

3+1 * 1+ 2

为了避免宏展开时,参数中操作符或邻近操作符之间作用,导致意外,应该使用括号将宏参数括起来。

#define MUT(x, y) (x) *(y)

#define替换

预处理时,字符串常量的值并不进行检查,所以如果需要把宏参数,插入到字符串中,有两种方法:

1.该方法只可以用于字符串参数,利用字符串相邻自动链接特性。

#include <stdio.h>
#define PRINT(FORMAT, VALUE) printf("The FORMAT is "FORMAT"\n", VALUE) int main()
{
PRINT("%d", 10);
return 0;
}

该方法只可以用于字符串。运行:

2.利用define预处理的宏参数进行转换,#arg被替换成arg代表的参数的字符串形式"arg"。

#include <stdio.h>
#define PRINT(FORMAT, VALUE) printf("The "#VALUE" value is "FORMAT"\n", VALUE) int main()
{
int x = 1;
PRINT("%d", x + 10);//x+10被替换成"x+10"
return 0;
}

运行:

宏与函数:

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

表达式中求较大值,利用宏来实现的优点是,宏是无类型的,但是会在每一处调用进行展开。宏还可以做一些函数无法实现的

#define MALLOC(n, type) ((type *)malloc(sizeof (type) * (n)))

申请n个type类型的内存空间

#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define MALLOC(n, type) ((type *)malloc(sizeof (type) * (n))) int main()
{
char *str;
str = MALLOC(10, char);
strcpy(str, "yang");
printf("%s", str); return 0;
}

运行:

带副作用的宏:

如果宏参数在宏定义中出现次数超过一次,这个参数如果具有副作用,那么这个宏带有副作用。

#include <stdio.h>

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

int main()
{
int x = 1;
int y = 2;
printf("%d", MAX(++x, ++y)); return 0;
}

运行:++具有副作用

#undef 移除一个宏定义

#include <stdio.h>

#define NUM 100

int main()
{ printf("%d",NUM);
#undef NUM
printf("%d", NUM);//此处将报错,以及移除宏定义了 return 0;
}

  运行:

二、条件编译:#if, #elif,#else,#endif,#ifdef,#ifndef

利用条件编译,可以选择代码一部分是正常编译还是完全忽略。

#include <stdio.h>
#define DEBUG 1 //#if对后面的表达式求值,如果非零(真)那么运行
#if DEBUG
#define NUM -100
#else
#define NUM 100
#endif int main()
{
printf("%d",NUM); return 0;
}

还支持#elif, 运行:

是否被定义:#ifdef , #ifndef

#ifdef DEBUG
#define NUM -100
#else
#define DEBUG 1
#define NUM 100
#endif

三、 文件包含#include

#include指令使另一个文件的内容被加入,被编译。当应用系统函数库文件时,使用中括号

#include <file.h>

当引入本地文件时,使用双引号

#include "file.h"

编译器先在本地查找头文件,如果找不到再去系统标准位置查找。

如果一个头文件,被多个文件包含,多个文件直接互相包含,会导致多次包含。可以使用条件编译,使头文件只被包含一次。

#ifndef __HEADFILE_H
#define __HEADFILE_H
//然后进行函数的声明等等
#endif

这样头文件,就只会被包含一次。但预处理器仍将读取这个文件,只是文件内容会被忽略。

四、#error指令

用于编译时生成错误信息

#ifndef SUCCESS
#error NO SUCCESS
#endif

五、#progma指令

因编译器而异,允许一些编译选项或其他方式无法实现的一些处理方式。如把汇编插入到C代码中

C和指针 第十四章 预处理器 头文件的更多相关文章

  1. C和指针 第十四章 习题

    14.1 打印函数 #include <stdio.h> void print_ledger_long(){ printf("function print_ledger_long ...

  2. C和指针 (pointers on C)——第十四章:预处理器

    第十四章 预处理器 我跳过了先进的指针主题的章节. 太多的技巧,太学科不适合今天的我.但我真的读,读懂.假设谁读了私下能够交流一下.有的小技巧还是非常有意思. 预处理器这一章的内容.大家肯定都用过.什 ...

  3. 《Linux命令行与shell脚本编程大全》 第十四章 学习笔记

    第十四章:呈现数据 理解输入与输出 标准文件描述符 文件描述符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误 1.STDIN 代表标准输入.对于终端界面 ...

  4. JavaScript高级程序设计:第十四章

    第十四章 一.表单的基础知识 在HTML中,表单是由<form>元素来表示的,而在javascript中,表单对应的则是HTMLFormElement类型.HTMLFormElement继 ...

  5. 第十四章——循环神经网络(Recurrent Neural Networks)(第一部分)

    由于本章过长,分为两个部分,这是第一部分. 这几年提到RNN,一般指Recurrent Neural Networks,至于翻译成循环神经网络还是递归神经网络都可以.wiki上面把Recurrent ...

  6. C++ Primer Plus学习:第十四章

    第十四章 C++中的代码重用 包含对象成员的类 将类的对象作为新类的成员.称为has-a关系.使用公有继承的时候,类可以继承接口,可能还有实现(纯虚函数不提供实现,只提供接口).使用包含时,可以获得实 ...

  7. 进击的Python【第十四章】:Web前端基础之Javascript

    进击的Python[第十四章]:Web前端基础之Javascript 一.javascript是什么 JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编 ...

  8. 【C++】《C++ Primer 》第十四章

    第十四章 重载运算与类型转换 一.基本概念 重载运算符是具有特殊名字的函数:由关键字operator和其后要定义的运算符号共同组成.也包含返回类型.参数列表以及函数体. 当一个重载的运算符是成员函数时 ...

  9. 【odoo14】第十四章、CMS网站开发

    第十四章.CMS网站开发** Odoo有一个功能齐全的内容管理系统(CMS).通过拖放功能,你的最终用户可以在几分钟内设计一个页面,但是在Odoo CMS中开发一个新功能或构建块就不是那么简单了.在本 ...

随机推荐

  1. [转载]我的Java后端书架 (2016年暖冬4.0版)

      [转载]我的Java后端书架 (2016年暖冬4.0版) ps:最近正在初学Java,有一些其他语言的底子,但是还是要好好看书,好好练习,网上找了好久,都没有这份书单来的实用,特意转载过来,方便以 ...

  2. 几个ES6新特性

    ES6是JavaScript语言的下一代标准,已经在2015年6月正式发布了,因为ES6的第一个版本是在2015年发布的,所以又称ECMAScript 2015(简称ES2015).本文主要讲述的是E ...

  3. jQuery+css3 弹幕

    写了个基于jQuery+css3的弹幕功能,此功能面向手机wap,利用改变位移做弹幕功能会使一些性能低的手机浏览器卡,所以用了css3,此功能不支持非webkit内核浏览器 html部分 自己设置样式 ...

  4. 【分享】国外后台界面HTML源码 [免费]

    国外后台界面HTML模版下载,里面的文字是英文的,不过可以修改成中文,带有数据统计界面和曲线图,本套模板相对完整,在主界面上点击那些菜单,都可以点开二级页面,希望对搞代码的程序员,对不擅长美工的朋友提 ...

  5. c语言之【#ifdef】

    电脑程序语句,我们可以用它区隔一些与特定头文件.程序库和其他文件版本有关的代码. 1 2 3 #ifdef 语句1     // 程序2 #endif 可翻译为:如果宏定义了语句1则程序2. 作用:我 ...

  6. python文件读写操作

    操作文件时一般经历以下步骤: 打开文件 操作文件 1.打开文件: 文件句柄 = open('/path/to/file_name','pattern') pattern: r:只读模式,打开文件时默认 ...

  7. 江太公:javascript count(a)(b)(c)(d)运行过程思考

    昨天,我弟抛给我一个js的题,使用类似标题那样的调用方法计算a*b*c*d以致无穷的实现方法.思考了半天,终于理清了它的运行过程,记录于下: 函数体: <!DOCTYPE html> &l ...

  8. VsFtpd配置文件详解

    1.默认配置:1>允许匿名用户和本地用户登陆.     anonymous_enable=YES     local_enable=YES2>匿名用户使用的登陆名为ftp或anonymou ...

  9. java分析源码-ReentrantLock

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  10. elk系列4之kibana图形化操作

    preface 我们都搭建了ELK系统,且日志也能够正常收集的时候,那么就配置下kibana.我们可以通过kibana配置柱状图,趋势图,统计图,圆饼图等等各类图.下面就拿配置统计图和柱状图为例,结合 ...