一、宏定义#define

优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率。代码可以写的通俗易懂。可以提高程序的清晰性、可读性,使于修改移植等。

缺点:宏定义的使用实际上也存在副作用,大量的使用会破坏程序的可读性,并给程序的调试带来麻烦,是优点也是缺点。过多的宏定义,代码不容易调试,代码进不去宏定义当前所运行的内容。

一般来说,如果一个函数非常大,一般不宜采用宏定义来进行改造,仅仅是那些小的函数,而且非常影响效率的函数才值得这样去做。

1. 不带参宏定义

例如: #define MAX  1000

 (1)宏名一般用大写

  (2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义

  (3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。

  (4)宏定义末尾不加分号;

  (5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。

  (6)可以用#undef命令终止宏定义的作用域

  (7)宏定义可以嵌套

  (8)字符串" "中永远不包含宏

2.带参的宏定义

例如:#define ADD(x,y) ((x)+(y))

1)实参如果是表达式容易出问题

  #define S(r) r*r

  area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;

  正确的宏定义是#define S(r) (r)*(r)

  (2)宏名和参数的括号间不能有空格

  (3)宏替换只作替换,不做计算,不做表达式求解

  (4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存

  (5)宏的哑实结合不存在类型,也没有类型转换。

  (6)函数只有一个返回值,利用宏则可以设法得到多个值

  (7)宏展开使源程序变长,函数调用不会

  (8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)

 (9)宏定义不分配内存,变量定义分配内存。宏替换发生的过程

二、 宏展开过程

为了理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程,见图。 

图1     C语言的编译过程

三、预处理器功能

其中预处理器产生编译器的输出,它实现以下的功能: 
(1)    文件包含 
可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。 
(2)    条件编译 
预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。 
(3)    宏展开 
预处理器将源程序文件中出现的对宏的引用展开成相应的宏 定义,即本文所说的#define的功能,由预处理器来完成。 
经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,这样才不会对此命令引起误解并误用。

四、样例贴代码

// 直接替换

#define  max   1000

// ##和# 的使用,##链接,#把字符变为字符串

#define  test(classname,len,type)\

char*  unit_test_binary_to_geometry_service_pid = "pj."#classname#len#type"id";\

#define  str(x)   #x

// 返回一个字符

#define getch(c) #@c

// 定义一个某类型的变量名称。

#define cat(x,y) x##y

void  main()

{

string str_ =  str(waht);

char* tmp_cat = "this is a test";

string cat(var,1235);

var1235 = tmp_cat;

char ch_ = ch(t);

test(A,12,int)

string temp = unit_test_pid;

}

自己的用例:

#define  unit_test_marco_derived_start(test_class_name,test_class_service_name,test_class_service_pid)\

test_class_service_name *          ___##test_class_service_name;\

void test_unit_module (unit_test_writer::ptr test_writer_);\

static char*  unit_test_##test_class_service_pid = "rw.unit.test."#test_class_name;\

\

class  unit_test_##test_class_name\

:public  unit_test\

{\

public:\

typedef rw_shared_ptr< unit_test_##test_class_name > ptr;\

typedef rw_shared_ptr<const unit_test_##test_class_name > const_ptr;\

\

unit_test_##test_class_name (unit_test_service* test_service_,runtime* runtime_)\

: _unit_test_service( test_service_ )\

, _runtime( runtime_ )\

{\

___##test_class_service_name = ( test_class_service_name * ) _runtime->get_service( test_class_service_pid )->get_service();\

}\

virtual ~ unit_test_##test_class_name (){}\

\

virtual void test(unit_test_result::ptr test_result_, unit_test_writer::ptr test_writer_)\

{\

test_writer_->write("\n -----------------start to test "#test_class_name"...---------------------\n");\

test_unit_module (test_writer_);\

test_writer_->write("\n -----------------end to test "#test_class_name"...---------------------\n");\

return;\

}\

private:\

unit_test_service*                 _unit_test_service;\

runtime*                           _runtime;\

private:\

};

当然宏定义的用法不止这么点,多种多样。

五、预处理命令

对于预处理命令,还有很多。也把别人的贴出来供各位参考:

  宏定义不分配内存,变量定义分配内存。宏替换发生的过程 
预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:

#define              定义一个预处理宏
#undef               取消宏的定义

#include            包含文件命令
#include_next   与#include相似, 但它有着特殊的用途

#if                      编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef                判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef             与#ifdef相反, 判断某个宏是否未被定义
#elif                  若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
#else                与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif              #if, #ifdef, #ifndef这些条件命令的结束标志.
defined            与#if, #elif配合使用, 判断某个宏是否被定义

#line                标志该语句所在的行号
#                      将宏参数替代为以参数值为内容的字符窜常量
##                   将两个相邻的标记(token)连接为一个单独的标记
#pragma        说明编译器信息

#warning       显示编译警告信息
#error            显示编译错误信息

说明:近期用了一些宏定义,所以就抽空整理了网上的部分东西。

若有问题,请随时联系!

宏定义#define整理相关推荐

  1. [C++]宏定义#define A B C

    C++关于宏定义的用法,有形如#define A B C的格式,此时B和C都是已知的字符串常量. 在宏定义中. 可以把两个常量字符串连在一起 如果#define A "a" 那么宏 ...

  2. 宏定义Define的一些用法

    ---转载百度文库 一. #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处 ...

  3. 《编码规范和测试方法——C/C++版》作业 ·003——宏定义作用整理、设计删除数组元素的函数

    文章目录 一.宏定义(#define)的作用 1.普通宏 2.带参宏 [注]:特殊用法 3.其他用法和注意点 二.实际问题(函数设计) 1.原题 2.题解参考 (1).面向过程的设计 (2).面向对象 ...

  4. VS无法使用宏定义#define解决方案

    在使用VS编译C语言或者其他语音用到宏定义#define,VS会报错提示(以VS2019为例) 解决方式: 在工具-->选项-->文本编辑器-->C/C++-->查看中,将&q ...

  5. [C语言]宏定义#define的使用详解

    一.宏定义定义常量 预定义符号 FILE //进行编译的源文件 LINE //文件当前的行号 DATE //文件被编译的日期 TIME //文件被编译的时间 STDC //如果编译器遵循ANSI C, ...

  6. C语言 | 预处理 | 宏定义 | #define | 定义函数

    文章目录 预处理 预处理运算符 宏定义 无参宏定义 带参宏定义 宏定义-定义函数 此文主要介绍宏定义,并在介绍宏定义时举例介绍预处理命令 预处理 参考:C 预处理器 | 菜鸟教程 重要的预处理器指令如 ...

  7. 预处理命令 宏定义 #define #undef

    预处理命令 源程序中以#开头的行称为预处理指令. 预处理指令并不是C语言的语法成分,而是传给编译程序的指令. 包括: 宏定义 #define #undef 文件包含 #include 条件编译 #if ...

  8. 枚举(enum)、宏定义(#define)、结构体(struct)的拾遗

    1.宏定义 1.1.不带参数的宏定义 #define 标识符 字符串           例如:#define PI 3.1415926 说明: (1)宏名一般习惯用大写字母表示,但并非规定,也可以用 ...

  9. C语言-宏定义#define的用法

    目录 1 不带参宏定义 2 带参宏定义 3 与字符串有关的用法 3.1 字符串转换 3.2 字符转换 3.3 字符连接 1 不带参宏定义 这种用法是最简单最常见的一种方式,如下: #define PA ...

最新文章

  1. 我把SpringBoot的banner换成了美女,老板:工作不饱和,建议加班
  2. 如何删除输入文本元素上的边框突出显示
  3. C++ 类和对象(一):类的概念、类的访问控制和封装、类对象模型、this指针
  4. Terminal中输入一行命令快速移动光标至行首行尾
  5. 数据结构-栈4-栈的应用-中缀转后缀
  6. 24口光纤配线架 cad块_光纤配线架cad画法
  7. 兴城职高计算机,兴城学计算机,兴城学计算机去哪里,兴城学计算机一般工资能拿多少 - IT教育频道...
  8. 删除小于一定尺寸的模型
  9. 聊聊索引失效的10种场景,巨坑
  10. plextv 找不到服务器,【Apple TV教程】从Plex流式传输
  11. 手把手带你从0搭建一个Golang ORM框架(全)!
  12. Java里面的Lambda表达式
  13. 程序关闭时在#pragma warning(suppress: 4985)处中断
  14. MinGW 是什么?
  15. 纳米红光更安全的养生方式——红光光浴#大健康#红光光浴#红光#种光光学
  16. 【算法训练营学习笔记-Week06】一遍不懂就多刷几遍
  17. 微型计算机中常见到的Ega.VGA等是指,大学计算机基础选择题汇总
  18. 用signalr实现简单的网页实时聊天
  19. python 输出\xhh格式的16进制数据(改2)
  20. WIN10-VS2019-SeetaFace6编译

热门文章

  1. 十年 Java API 版权案终落地、Log4j 漏洞蛰伏八年后席卷全球,2021 年开源圈大事件盘点
  2. 单张PPT转成单张PDF的PDF文件怎么设置打印出一页纸有6页PPT
  3. 数字上的错误后缀_域名创业方法之前后缀完美搭配
  4. 自然语言描述的空间实体自动摆放
  5. 中国传统的婚姻观,害了男人,也害了女人
  6. 程序员麦兜【编程笔记】-看了一点面试题
  7. assignment from incompatible pointer type
  8. AHOI/JSOI 2014 骑士游戏 题解
  9. SPA设计与架构-理解单页面Web应用 (埃米顿.A斯科特) 中文pdf扫描版
  10. Android Camera HAL3 - Multi Camera(1)