#define 创建一个宏,该宏是标识符或參数化标识符与标记字符串的关联。

在定义宏之后。编译器可用标记字符串替换源文件里标识符的每一个匹配项。

双击以所有折叠。">语法

#define identifier token-string

#define identifier ( identifier 1 , ... , identifier n ) token-string

">备注

1 #define 指令促使编译器用 token-string 替换源文件里 identifier 的每一个匹配项。 仅当 identifier 构成标记时才替换它。 也就是说,假设 identifier 出如今凝视、字符串或较长的标识符中。则不会替换它。

2 另外一种形式类似于函数,比如

#define mul(a,b) (a*b) 形參名称将出如今 token-string 中以标记实际值的替换位置。

token-string 中前面未带stringizing (#)、charizing(#@)
或 token-pasting (##) 运算符或后面未跟 ## 运算符的每一个形參将由相应的实參替换。

注意:

1 宏就是简单的字符替换,注意替换后的运算符优先级可能会影响宏定义所要表达的。所以要善于使用小括号。比如:

#define Add(a,b) a+b  假设使用的时候:2*Add(1,2) 原本想让它等于6,但替换后变成2*1+2=4。

所以要注意。

2 #define中的换行符是反斜杠\。

假设一行没写完。直接加一个\,下一行继续写就能够了。

3 注意这里仅仅是字符替换。宏定义中不应含有return等语句。想一想替换后。会变成什么样子。

宏的返回值的两种形式:

1 操作符。

#define Max(a,b) (((a)>(b))(a):(b))

#define add(a,b) ((a)+(b))

2 将返回值赋值给一个额外的形參。这个形參就是返回值。

#define cal(a,b,c) {c=a+b;}

一个很有意思的样例:

定义一个求最大值的宏。

可能会这么写:#define Max(a,b) ((a)>(b) ?

a):(b))

这么做可能对于大多数情况是没有错误的,可是事实上这么做是不严谨的。比如:

#define Max(a,b) ((a)>(b)? (a):(b))

int fun(int *a)

{

*a=*a+1;

return *a;

}

main()

{

int a=1,b=2,c;

c=Max(a,fun(&b));

}//我们想得到的c的值应该是3,但实际会发现c的值是4.

由于首先我们替换:c=((a)>(fun(&b))?

(a):(fun(&b)));

能够发现fun运行了两次。b的值加了两次变成了4.所以结果是4.

这里给出一个严谨的做法:

使得參数仅仅被运行一次。

#define Max(a,b) ({\

typeof(a) _a=(a);\

typeof(b) _b=(b);\

(_a>_b)? _x : _y; })

这样就不会有上述的问题了。

注意:({...})的作用是将内部的几条语句中最后一条的值返回,它也同意在内部声明变量(由于它通过大括号组成了一个局部Scope)。用此能够达到return的目的。

!!

注:这里使用了typeof。它是c的一个新扩展。而在vs2005,2010,2013中都无法使用。

仅仅能在在线编译器下运行。结果是对的。

观察发现:vs中不识别keywordtypeof了。在C++中可用decltype实现相似功能,求某个变量的类型。并且vs中也不能够有这种({...})的东西了。

要么#define..
() 要么#define .. {}。

所以上面的做法能够改成:

#define MIN(X,Y,M) {\

decltype(X)x_ = (X);\

decltype(Y)y_ = (Y);\

M=(x_ < y_) ? x_ : y_; }

使用时:int a=1,b=2,c; Max(a,b,c);c为返回值。不參与运算。

#与##与#@在#define中的使用方法:

#的意思是不展开參数

假设在token-string  中出现以#开头。意思是:不展开參数。直接替换。

假设在token-string  中出现不以#开头,意思是:展开參数。直接替换。

比如:

#define f(a) a+1

#define T(a) #a

#define H(a) a

T(f(a))->f(a)->a+1

H(f(a))->H(a+1)->a+1

尽管结果一样,可是过程不一样。

##的意思是字符串连接符

比如:

#define f(a,b) a##b##lobe

结果就是ablobe

注意:##不能出如今开头,也不能出如今结尾。仅仅能出如今中间。

#@字符化运算符

Microsoft 专用

charizing 运算符仅仅能与宏的參数一起使用。 假设宏的定义中的形參前有 #@。则会在扩展宏时用单引號括起实參并将其视为一个字符。

#define makechar(x)  #@x

==

char a= makechar(x);

比如:

#define H(x) #@x

cout<<H(a)<<endl;

输出结果:a

cout<<H(ab)<<endl;

输出结果:24930

注解:就是相当于把#@后面的实參变成一个字符型的字符。

#define的使用方法体会的更多相关文章

  1. tornado 的 define 和options方法解读

    一.源码解读 tornado是facebook开源的非阻塞web容器,类似java的netty,tornado.options是负责解析tornado容器的全局参数的,同时也能够解析命令行传递的参数和 ...

  2. Unable to execute dex: Multiple dex files define 的解决方法

    我们在引入library时可能会出现这个错误 比如: [2013-11-05 14:22:15 - Dex Loader] Unable to execute dex: Multiple dex fi ...

  3. FXC Define的使用方法

    https://docs.microsoft.com/en-us/windows/desktop/direct3dtools/dx-graphics-tools-fxc-syntax https:// ...

  4. #define使用方法

    1.简单的define定义 #define MAXTIME 1000 一个简单的MAXTIME就定义好了,它代表1000,假设在程序里面写 if(i<MAXTIME){.........} 编译 ...

  5. define 的全部使用方法

    typedef的总结,以下是引用的内容(红色部分是我自己写的内容). 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如: char* pa, pb; // 这 ...

  6. iOS常用系统信息获取方法

    一.手机电量获取,方法二需要导入头文件#import<objc/runtime.h> 方法一.获取电池电量(一般用百分数表示,大家自行处理就好) -(CGFloat)getBatteryQ ...

  7. php中const与define的使用区别 详解

    1.const用于类成员变量定义,一旦定义且不能改变其值.define定义全局常量,在任何地方都可以访问. 2.define不能在类中定义而const可以. 3.const不能在条件语句中定义常量 i ...

  8. PHP 中const 与define 区别

    1.const用于类成员变量定义,一旦定义且不能改变其值.define定义全局常量,在任何地方都可以访问. 2.define不能在类中定义而const可以. 3.const不能在条件语句中定义常量 i ...

  9. const与define的使用区别

    1.const用于类成员变量定义,一旦定义且不能改变其值.define定义全局常量,在任何地方都可以访问. 2.define不能在类中定义而const可以. 3.const不能在条件语句中定义常量 i ...

随机推荐

  1. c# 中文字符(全角、半角)通用处理

    声明:本文仅提供一种编程思路,所提供代码仅供参考,如需使用,请自行完善. 我们在做程序的的时候经常要处理用户输入,作为我们的主要语言中文,经常会出现全角.半角的问题,这会在查询时给我们带来很多麻烦.本 ...

  2. LRC CRC 纵向冗余码校验

    LRC CRC 纵向冗余码校验   2010-01-26 11:00:15|  分类: 电气 |  标签: |字号大中小 订阅  1.LRC校验  LRC域是一个包含一个8位二进制值的字节.LRC值由 ...

  3. Javascript中的原型链、prototype、__proto__的关系

    javascript  2016-10-06  1120  9 上图是本宝宝用Illustrator制作的可视化信息图,希望能帮你理清Javascript对象与__proto__.prototype和 ...

  4. Android自定义View(二)

    前言 魅族手机的闹钟应用中有个倒计时,这个控件还是蛮有趣的.左边是魅族闹钟,右边是我们最终实现的效果,虽然有些细节还需优化,不过基本上已经达到了想要的效果,我们先来就来看看如何实现吧. 分析 确定宽高 ...

  5. VUE -- 用组件上传文件和用xmlrequest上传

    xmlrequest: sendForm(str, types) { var form = this.$refs.ipas_form; var oOutput = document.querySele ...

  6. Android录制视频报错setVideoSize called in a invalid state 1

    录制视频时想获取手机支持的录制视频的分辨率,使用代码如下: List<Camera.Size> videoSize = camera.getParameters().getSupporte ...

  7. WEB安全漏洞与防范

    1.XSS 原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的.如,盗取用户Cookie信息.破坏页面结构.重定向到其 ...

  8. 资源相互引用时 需添加 PerformSubstitution=True

    获取或设置一个布尔值,该值确定在对由 WebResourceAttribute 类引用的嵌入式资源的处理过程中是否分析其他 Web 资源 URL,并用到该资源的完整路径替换. 如:一个CSS文件引用其 ...

  9. 利用【深度网络】高效提取feature

    extracting features from a learned model, and add some new features yourself.

  10. python 常用的模块(hashlib)转

    摘要算法简介 Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串( ...