宏的几种特殊用法

1. 屏蔽“未使用参数”警告

在OceanBase中ob_define.h中就使用了这种宏,将传入的数据强制转化为void型。

    #ifndef UNUSED
    #define UNUSED(v) ((void)(v))
    #endif

这种宏主要是为了屏蔽“未使用参数”的警告,如下面这个函数用两个参数,但是一个都不用的话,某些编译器就会报出警告:认为p和mod_id都没有使用。所有我们使用UNUSE宏,这样两个参数都被使用了,但是实际上没有做任何有效的动作,以此来屏蔽“未使用参数”警告。

 virtual void mod_free(void* p, const int32_t mod_id = 0)
 {
    UNUSED(p);
    UNUSED(mod_id);
 }

2. 指定字节对齐

在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对界条件:

1) 使用伪指令#pragma pack (n),编译器将按照n个字节对齐。

2) 使用伪指令#pragma pack (),取消自定义字节对齐方式。

另外,还有如下的一种方式:

3) __attribute__((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

4) __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。

#define CACHE_ALIGNED __attribute__((aligned(CACHE_ALIGN_SIZE)))

3. 可变参数宏

我们指定,有些函数的参数是可变的,例如printf函数,指定第一个为格式化字符串以后,后面可以跟个数不定的参数,同样,宏也可以指定多个参数。有两种方法可以做到。

一是使用args...##args,二是使用...__VA_ARGS__。下面是两种方式定义的两个宏,这两个宏都能在printf字符串前,先输出一个字符串,达到相同的效果。

#define P_Debug(format,args...) {    printf("[DeBug]");    printf(format,##args);}while(false)
#define P_Release(format,...) \do{    printf("[Release]");    printf(format,__VA_ARGS__);}while(false)

使用的时候为:

P_Debug("%s:%d\n","good",100);
P_Release("%s:%d\n","good",100);

4. ###,#@的区别

假设定义3个宏,

#define A(x) T_##x#define B(x) #@x#define C(x) #x

则下面展开后为

A(1)------>T_1

B(1)------>‘1‘

C(1)------>"1"



欢迎光临我的网站----蝴蝶忽然的博客园----人既无名的专栏

如果阅读本文过程中有任何问题,请联系作者,转载请注明出处!

宏的几种特殊用法,布布扣,bubuko.com

时间: 2024-10-22 15:01:06

宏的几种特殊用法的相关文章

do...while(0)在宏定义中的巧妙用法

大家都知道,do-while(condition)可以表示循环,但你有没有遇到在一些宏定义中可以不用循环的地方,也用到了 do-while.比如: #define DELETE_POINTER(p) do { if(NULL != p) delete p; p = NULL; }while(0) 这时,do-while(0)的功能就不仅仅是循环了,这是do..while(0)的一种巧妙用法.它有以下几种功能: 1.在后面要加分号,使调用如同函数:调用如下: int* p = new int(5)

关于function的一种常用用法

关于function的一种常用用法 void Share::InitAcrossManager() { GsMgrEvent gsMgrEvents;//保存function的结构体 gsMgrEvents.fnSendData2Client = [this](int nChannelId, void* pData, int nLen)//lambda绑定,当然也可以用std::bind进行绑定 { SendCmd2C(nChannelId, s2c_prop_opt, pData, nLen)

java数组复制的几种常见用法

1.1数组复制的几种常见用法 1.1.1System.arraycopy的用法 int[] src = {1,3,5,7,9,11,13,15,17}; int[] dest = {2,4,6,8,10,12,14,16,18,20}; //从src中的第一个元素起复制三个元素,即1,3,5复盖到dest第2个元素开始的三个元素 System.arraycopy(src, 0, dest, 1, 3); System.out.println(Arrays.toString(dest)); 结果为

LinkedList的一种错误用法

最近在做图像处理的时候,发现某一段代码非常的慢,慢得让人无法接受.主要的代码是顺序访问一个LinkedList的元素,效果是随着index的变大,速度越来越慢,list的元素个数在百万以上.找到原因,分享出来,也希望大家不要跳入同一个陷阱.还是那一句话,可运行的代码和高质量的代码之间还是有比较远的距离. LinkedList错误用法示例 代码里面加入了一些打印时间相关的代码,主要是为了直观的显示运行的耗时. 错误代码 public static void main(String[] args)

@GeneratedValue 四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO

一.JPA通用策略生成器 JPA提供四种标准用法,由@GeneratedValue的源代码: @Target({METHOD,FIELD}) @Retention(RUNTIME) public @interface GeneratedValue{ GenerationType strategy() default AUTO; String generator() default ""; } 其中GenerationType: public enum GenerationType{ T

TL431的几种常用用法

TL431的主要作用是使得电路获得更稳定的电压,TL431是一种较为精密的可控稳压源,有着较为特殊的动态阻抗.其动态响应速度快,输出噪声低,价格低廉. 注意上述一句话概括,就是便宜,精密可控稳压源TL431. TL431的输出电压可以通过两个电阻任意地设置到从2.5V到36V电压,工作电流可以从0.1~100mA,输出电压纹波低. 几种常用的用法如下: 上图中,REF为参考端,Anode为阳极,CATHODE为阴极.由于TL431内部自带2.5V基准源,所以对于图(1)的TL431接法,输出一个

(转) c/c++调用libcurl库发送http请求的两种基本用法

libcurl主要提供了两种发送http请求的方式,分别是Easy interface方式和multi interface方式,前者是采用阻塞的方式发送单条数据,后者采用组合的方式可以一次性发送多条数据 一.Easy interface libcurl的easy interface是最基本的用法,简要流程为: 1.在主线程中调用curl_global_init(CURL_GLOBAL_ALL)初始化 2.调用curl_easy_init获取一个句柄: 3.调用curl_easy_setopt函数

Qt中两种定时器用法

在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度. 1.QObject类的定时器 QObject是所有Qt对象的基类,它提供了一个基本的定时器.通过QObject::startTimer(),可以把一个一毫秒为单位的时间间隔作为参数来开始定时器,这个函数返回一个唯一的整数定时器的标识符.这个定时器开始就会在每一个时间间隔"触发",直到明确的使用这个定时器的标识符来调用QObje

Android之Toast通知的几种自定义用法

Toast在手机屏幕上向用户显示一条信息,一段时间后信息会自动消失. 1.默认用法 [html] view plain copy print? Toast.makeText(getApplicationContext(), "默认Toast样式",Toast.LENGTH_SHORT).show(); 2.Fragment中的用法 [html] view plain copy print? Toast.makeText(getActivity(),"网络连接错误,请检察网络设