凡是以 “#”开头的均为预处理命令!

其定义的一般形式为:

  #define  标示符  字符串

对于宏定义说明以下几点:

1.宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现!

2.宏定义不是说明或语句,在行末不需要加上分号,若加上分号则连分号一起置换。

3.宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可以使用 “#undef”命令。

4.宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。

5.宏定义允许嵌套,在宏定义的字符串中可以使用定义的宏名。在宏展开时由预处理程序层层代换

6.习惯上宏名用大写字母表示,以便于与变量区别!

7.可用宏定义表示数据类型,是书写方便。 例如 #define INTEGER int

#define 与 typedef 的区别:宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简单的代换,而是对类型说明符重新命名。被命名的标示符具有类型定义说明的功能。typedef 后面会有分号,表示语句的结束。

一、无参数的宏定义

下面一段小程序,说明 #define 与 typedef 的区别:

 #define PIN1 char* // 宏定义
typedef char* PIN2; // 重类型说明符重新命名 int main(void) {
PIN1 x, y;
PIN2 a, b;
printf("By #define : %lu %lu\n\n", sizeof(x), sizeof(y));
printf("By typedef : %lu %lu\n\n", sizeof(a), sizeof(b));
// 替换之后
/*
char *x, y; // x为一个指针, y是一个字符型
char *x, *y; // x, y均为指针类型
*/
return ;
}

打印结果:

 By #define : 8 1 // 在我当前环境,指针类型占8个字节,char字符站1个字节

 By typedef :  8 // x, y均为指针类型

编程中,适当使用宏定义可以提升我们的开发效率,但是慎用!

不用循环和递归,实现打印0-999:

 #define BD(x) x;x;x;x;x;x;x;x;x;x;
int main(void) {
int n = ;
BD(BD(BD(printf("%d\n", n++))));
}

二、带参数的宏定义

C语言允许宏有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。

对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

带参宏定义的一般形式: #define  宏名(形参表)  字符串

对于带参数的宏定义有以下问题需要注意:

1.带参数的宏定义,宏名和参数表之间不能有空格出现

例如:

 #define MAX(a,b)  ((a > b) ? a : b)  // 正确写法
#define MAX (a,b) ((a > b) ? a : b) // 错误写法

2.在带参数宏定义中,形式参数不分配内存单元,因为不必作类型定义。而宏调用中的实参有具体的值。要用他们去代换形参,因此必须作类型说明符。

3.在宏定义中的形参是标示符,而宏调用中的实参可以使表达式。

4.在宏定义中,字符串中的形参通常要用括号括起来以避免出错。

 #define PT(x) (x) * (x)
#define BT(x) x * x
int main(void) {
printf("PT=%d\nBT=%d\n", PT( + ), BT( + ));
}

5.带参数的宏和带参数的函数相似。但本质上不同!!

条件编译

预处理程序提供了条件编译的功能。可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试时很有用的。不建议是用 /**/ ,因为C语言中不可以多行注释嵌套多行注释。建议使用预处理条件编译注释。

示例:

 int main(void) {
#if 0
printf("-----------"); // 此处肯定不会执行
#endif
printf("Learning and record\n");
}

条件编译有三种潜规则:

第一种形式:

#ifdef 标示符
程序段1
#else
程序段2
#endif

或:

#ifdef 标示符
程序段2
#endif

功能:如果标示符已被 #define 命令定义过则对"程序段1"进行编译;否则对"程序段2"进行编译

第二种形式:

#ifndef 标示符
程序段1
#else
程序段2
#endif

功能:如果标示符没有被 #define 命令定义过则执行"程序段1";否则执行"程序段2"

场景:如果没有定义“标示符”,我们可以在“程序段1”位置定义“标示符”,以确保这个标示符的存在。

示例:

int main(void) {
// 若该宏未定义
#ifndef STRING
// 则给予定义
#define STRING "Learning and record……\n"
#endif
// 方便我们使用
printf("---%s", STRING);
}

第三种形式:

#if 常量表达式
程序段1
#else
程序段2
#endif

功能:如果“常量表达式”为真,则执行“程序段1”,反之执行“程序段2”

尊重作者劳动成果,转载请注明: 【kingdev】

C语言预处理_05的更多相关文章

  1. 面试问题4:C语言预处理包括哪些

    问题描述:C语言 预处理包括哪些操作 C语言的三种预处理包括:宏定义(#define).文件包含(#include).条件编译(#if.#else.#endif). 对于宏定义的介绍: 宏定义必须写在 ...

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

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

  3. C语言预处理运算符

    转自C语言预处理运算符 预处理还需要运算符?有没有搞错? ^_^, 没有搞错,预处理是有运算符,而且还不止一个: #(单井号)    -- 字符串化运算符. ##(双井号 )-- 连接运算符 #@   ...

  4. C语言预处理指令的初步了解

    所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理是C语言的一个重要功能,它由预处理程序负责完成.当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分 ...

  5. C 语言入门第八章--C语言预处理命令

    例如:#include ,这种以#号开头的命令称为预处理命令. ===C语言宏定义(#define的用法)==== #define 叫做宏定义命令,它也是C语言预处理命令的一种.所谓宏定义,就是用一个 ...

  6. C语言预处理理论2

    C语言预处理理论1.头文件包含(1)#include <>和#include ""区别:<>专门用来包含系统提供的头文件(就是系统自带的,不是程序员自己写的 ...

  7. C语言预处理理论

    C语言预处理理论1.从源码到可执行文件的过程(1)源码.c->(编译)->elf可执行程序(2)源码.c->(编译)->目标文件.o->(链接)->elf可执行程序 ...

  8. C语言预处理编译链接各个阶段错误,分阶段的说一下

    C语言预处理编译链接各个阶段错误,分阶段的说一下 C语言预处理编译链接各个阶段错误,分阶段的说一下比如指针异常,数组下标越界什么的    我来答 1个回答 #热议# 你觉得这辈子有希望看到996消失 ...

  9. C语言 预处理三(条件编译--#if)

    //#if 条件编译 //一般用于产品各个版本的语言包 #include<stdio.h> #include<stdlib.h> //#都是预处理指令,条件表达式必须在预处理里 ...

随机推荐

  1. 洛谷 P2048 [NOI2010]超级钢琴(优先队列,RMQ)

    传送门 我们定义$(p,l,r)=max\{sum[t]-sum[p-1],p+l-1\leq t\leq p+r-1 \}$ 那么因为对每一个$p$来说$sum[p-1]$是一个定值,所以我们只要在 ...

  2. SequoiaDB培训视频

    很久之前录制的SequoiaDB培训视频,现在都放上百度云盘了,感兴趣的同学可以看看. 第一讲:图形界面-安装前准备 链接: https://pan.baidu.com/s/1d2B3qUYqtKrE ...

  3. 关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error

    什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).Thin ...

  4. Python-15-收集参数

    允许用户提供任意数量的参数: def print_params(*params): print(params)   >>> print_params('Testing') ('Tes ...

  5. CC17:猫狗收容所

    题目 有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,第一种为直接收养所有动物中最早进入收容所的,第二种为选择收养的动物类型(猫或狗),并收养该种动物中最早进入收容所的. 给定一 ...

  6. Ubuntu 最新设置阿里云更新源

    可将 http://cn.archive.ubuntu.com/ubuntu/ 替换为下列任意服务器: Ubuntu 官方(欧洲,国内较慢,无同步延迟) http://archive.ubuntu.c ...

  7. python之字典的相关操作

    一.什么是字典 dict 用{}表示,用来存放键值对数据 {key:value} 键:具有唯一性,不能重复,不可变 必须是可哈希的(不可变的数据类型) 字典是无序的,没有索引 值: 没有任何限制 已知 ...

  8. Linux之shell命令实现-批量去掉文件名中空格,以及批量修改文件名为数字序号文件名

    1 shell下批量出去文件名中的空格 执行看现象: 上面的是执行for循环以后看到的: 然而源目录下的文件如下: 这样的话想要cat某个具体文件是拿不到的,所以需要去空格处理: 处理方式有很多:如 ...

  9. [原]Maven项目编译后classes文件中没有.xml问题

    在做spring+mybatiss时,自动扫描都配置正确了,却在运行时出现了如下错误.后来查看target/classes/.../dao/文件夹下,发现只有mapper的class文件,而没有xml ...

  10. [转]兼容各个浏览器的H.264播放: H.264+HTML5+FLOWPLAYER+WOWZA+RMTP

    一.方案确定 计划做视频播放,要求能够播放H264编码的mp4文件,各个浏览器,各种终端都能播放. 首先查找可行性方案, http://www.cnblogs.com/sink_cup/archive ...