C语言第十一回合:预处理命令的集中营

 

【学习目标】

 

1.         宏定义

2.         文件包括”处理

3.         条件编译

预处理命令:能够改进程序设计的环境。提高编程效率。

其功能主要有三种:宏定义、文件包括、文件编译。

ANSI标准定义的C语言预处理指令预览表

A: 宏定义

(a)不带參数的宏定义

格式:#define标识符 字符串

如:#define PI 3.1415926

*标识符被称为:宏名

*在预编译时将宏名替换成字符串的过程为:宏展开。

*#define 是宏定义命令
//求圆周长
#include <stdio.h> #define PI 3.1415926 int main( void )
{
float r; //半径
float c; //周长 r= 3.0; c= 2* PI* r; //求圆周长 printf("%.3f\n", c ); //保留3为小数 return 0;
}

PS:

(1) 宏名一般为大写字母表示,便于差别。但也能够是小写的

(2)使用宏名替换能够降低代码量。易于维护

(3) 宏定义不是C语句。所以不必在末尾加分号。假设加了分号,会宏名会替代字符串和分号

#define NUM 123;  //有分号。编译器会报错!!

(4)      能够用#undef命令中止宏定义的作用域。否则其作用域由開始定义本文件结束。

//#undef的使用
#include<stdio.h> int main( void )
{
#define N 20 //N替代20 printf( "%d\n", N ); #undef N //结束N的作用域。假设没有这条语句提示redefined #define N 30 //N替代 30 printf( "%d\n", N ); return 0;
}

(5)宏定义时,能够引用已定义的宏名,能够层层置换

如:

#include<stdio.h>

#define R 3.0
#define PI3.1415926
#define C2*PI*R
#define SPI*R*R int main( void)
{
//打印圆的半径R。周长C,面积S
printf( "R= %.2f\n", R );
printf( "C= %.2f\n", C );
printf( "S= %.2f\n", S ); return 0;
}

(6)对于程序中有“”(双撇号括)括起来的字符串内的字符,即使与宏名同样,也不进行置换。

如:

#include<stdio.h>

#define stringhello,world!
#define STRING"hello,world!" int main( void )
{
printf( "string" ); //string没有被替换为hello,world! putchar( '\n' ); //换行 printf( STRING ); //被替换为hello,world! return 0;
}

执行结果:

string

hello,world!

(7)      宏定义有别于变量的定义。宏定义仅仅做字符替换,不分配存储空间

(b) 带參数的宏定义

作用:进行參数的替换

格式:#define宏名(參数表)  字符串

[ 1 ]ADD带參数的宏

#include <stdio.h>

//带參数的宏替换
#define ADD( a, b ) ( (a)+ (b) ) //每一个变量使用括号是防止替换后有歧义 int main( void )
{
int n= 10;
int m= 20;
int sum= 0; sum= ADD( n, m ); printf( "%d\n",sum ); return 0;
}

[ 2 ]SIZEOF带參数的宏替换。

能够求数组的长度(记住sizeof的使用有限制!)

/*
使用说明:
strlen()函数仅仅能求字符串的长度
sizeof不能求作为传递參数的数组原本的大小
*/
#include <stdio.h> //定义SIZEOF宏
#define SIZEOF( array) ( sizeof( array )/ sizeof( array[ 0 ] ) ) int main( void )
{
int num= 0;
int array[]= { 1, 2,3, 3, 7, 22, 33, 44, 5, 5, 6, 7, 10 }; num= SIZEOF( array );
printf( "array的长度为%d\n",num ); return 0;
}

执行结果:

array的长度为13

PS:

(1)     对于带參数的宏,按从左到有进行置换。假设字符串中的字符不是參数字符(如a+ b中的+)要保留。

(2)      在宏定义的宏名与參数的括号之间不能加空格,否则会被当作字符串的一部分

注意:函数与宏的差别

(1)     使用宏的次数多时,宏展开后程序的长度会增长;而函数的调用不会。

(2)     宏的替换不占用执行时间。仅仅占用编译时间。而函数则占用执行时间(即分配单元、值传递、返回等)

B: 文件包括”处理

“文件包括”处理:一个源文件能够将另外一个源文件的所有包括进来。

格式:(a)#include“文件名称”

(b)#include <文件名称>

两种格式的差别:使用尖括号表示在包括文件(即库文件)文件夹中去查找(包括文件夹是由用户在设置环境时设置),而不在源文件文件夹去查找;使用双引號则表示首先在当前的源文件文件夹中查找,若未找到才到包括文件夹(库文件)中去查找。

PS:

(1)  一个#include命令仅仅能包括一个源文件,多个源文件要多个#include的命令

(2)    假设文件1要包括文件2,而文件2要包括文件3,则能够在文件1中用两个#include命令分别包括文件2和文件3,并且文件3必须出如今文件2前。

(3)  文件包括能够嵌套使用。即一个包括文件能够包括一个被包括的文件

(4)  被包括文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。因此,假设file2.h中有全局静态变量,它也在file1.h文件里有效,不必用extern声明。

C:条件编译

条件编译:是对部分内容指定编译的条件,是其满足一定条件才进行编译。

格式:

(1)

#ifdef  标识符

程序段1

#else

程序段2

#endif

作用:假设标识符被#define定义过,就进行程序段1的编译;反之对程序段2进行编译。假设没有程序段2,能够对#else省略。

#include<stdio.h>

#define R3.0   //定义R

int main(void )
{
#ifdef R //相似于if-else printf( "已经定义了R\n"); #else printf( "未定义R\n"); #endif //条件推断结束 return 0;
}

(2)

#ifndef 标识符

程序段1

#else

程序段2

#endif

作用:假设标识符没有被#define定义过,则对程序段1进行编译;反之对程序段2进行编译。

(3)

#if 常量表达式

程序段1

#else

程序段2

#endif

作用:假设表达式的值为真(即非0)。则就对程序段1进行编译。反之对程序段2进行编译。

#include <stdio.h>

#define R 3.0   //定义R

int main( void )
{
#ifndefR //相似于if-else printf("未定义了R\n" ); #else printf("已经有定义R\n" ); #endif //条件推断结束 return0;
}

【指尖的微笑】错误在所难免,希望得到大家的指正^-^

转载时保留原文的链接http://oursharingclub.joinbbs.net/和http://blog.csdn.net/mirrorsbeyourself

C语言第十一回合:预处理命令的集中营的更多相关文章

  1. C语言第十一讲,预处理命令.

    C语言第十一讲,预处理命令. 一丶预处理简介 什么是预处理,预处理就是预先处理. 我们知道,程序会经过编译,连接形成可执行文件 这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理.提前 ...

  2. C++学习(二十七)(C语言部分)之 预处理命令

    结构体 联合 枚举 联合 只能保存最后赋值的结果枚举 所有可能值列出来 预处理命令是在编译前期的阶段 代码-(编译)-->可执行文件(exe)预编译 编译前对代码处理 *1.插入头文件的内容 # ...

  3. 【C语言入门教程】2.8 C 语言的预处理命令

    预处理命令是在程序编译阶段进行执行的命令,用于编译与特定环境相关的可执行文件.预处理命令扩展了 C 语言,本节将选择其中一些常用的预处理命令进行讲解. 2.8.1 宏替换命令 宏替换命令的作用类似于对 ...

  4. 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出

    [源码下载] 不可或缺 Windows Native (4) - C 语言: 预处理命令,输入,输出 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 预处理命令 输入 ...

  5. C语言之预处理命令

    /**************************************************************************** Title:C之预处理命令 Time:201 ...

  6. C语言预处理命令总结大全

    C程序的源代码中可包括各种编译指令,这些指令称为预处理命令.虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境.本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性.ANS ...

  7. C语言预处理命令详解

    一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置. 预处理是C语言的一个重要功能 ...

  8. C语言之预处理命令与用typedef命名已有类型

    预处理命令 主要是改进程序设计环境,以提高编程效率,不属于c语言本身的组成部分,不能直接对它们进行编译,必须在对 程序编译之前,先对程序中的这些特殊命令进行“预处理”.比如头文件. 有以下三类:宏定义 ...

  9. C语言中的预处理命令

    预处理功能是C语言的重要功能. 问:为什么要预处理,什么是预处理? 答:我们知道高级语言的运行过程是通过编译程序(编译器)把源代码翻译成机器语言,实现运行的.编译程序的工作包含:语法分析.词法分析.代 ...

随机推荐

  1. Android 卡顿优化 1 卡顿解析

    1, 感知卡顿 用户对卡顿的感知, 主要来源于界面的刷新. 而界面的性能主要是依赖于设备的UI渲染性能. 如果我们的UI设计过于复杂, 或是实现不够好, 设备又不给力, 界面就会像卡住了一样, 给用户 ...

  2. longest-repeating-character-replacement(难)

    用sliding window的方法,之前还有个k不同元素好像也是类似的思路.有时间可以去复习下. https://leetcode.com/problems/longest-repeating-ch ...

  3. VLAN讲解

    VLAN(Virtual Local Area Network)的中文名为"虚拟局域网".VLAN是一种将局域网设备从逻辑上划分成一个个网段,从而实现虚拟工作组的新兴数据交换技术. ...

  4. redis-3.28 一主二从模式介绍、主从从模式介绍、sentinel模式一主两从高可用

    一.redis-3.28部署 yum install gcc tclwget http://download.redis.io/releases/redis-3.2.8.tar.gztar -zxvf ...

  5. KL变换和PCA的数学推导

    一些推导的笔记 上面分解成无穷维,大多数时候都不是的吧... 这里的d有限维,应该是指相对小于上面的分解的维度的某个数 参考资料 参考资料,上面是从最小化损失的角度,利用拉格朗日对偶的优化方法求解 p ...

  6. 【笔记】js原生方法 在元素外部或内部实现添加元素功能(类似jq 的 insert 和 append)

    介绍的这个方法是:insetAdjacentHTML() 方法 此方法接收两个参数: 第一个参数必为下列值: beforebegin:在调用的元素外部的前面添加一个目标元素 afterend:在调用元 ...

  7. decorator在Python中的作用

    decorator(装饰器)在python中作用,可以起到代码复用,也可以起到AOP(面向横切面)的作用. 另外很重要的一点应该就是function在python的世界中是作为一等公民存在的. 在py ...

  8. 从0x00到0xFF的含义以及二进制到10进制的转换(转)

    转载自: http://www.cnblogs.com/brice/p/5343322.html 对于二进制来说,8位二进制我们称之为一个字节,二进制的表达范围值是从0b00000000-0b1111 ...

  9. 用户手册是Yasm汇编

    本文档的用户手册是Yasm汇编. 它是介绍和通用所有Yasm用户参考. 英文的参考:http://www.cnblogs.com/coryxie/p/3959888.html 1 .介绍 Yasm b ...

  10. [Angular] AfterContentChecked && AfterViewChecked

    AfterContentChecked & AfterViewChecked are called after 'OnChanges' lifecycle. And each time 'ng ...