C++宏,同名宏,宏的井号
https://blog.****.net/s9434/article/details/79871598
https://blog.****.net/qq_33658067/article/details/79443014
https://blog.****.net/s9434/article/details/79871598
http://bbs.51cto.com/thread-1094029-1-1.html
#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
即CINIT(na,t,nu) 为 CURLOPT_连接na=CURLOPTTYPE_连接t+nu
CURLOPT_WRITEFUNCTION的定义为CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11)即为
CURLOPT_WRITEFUNCTION=CURLOPTTYPE_FUNCTIONPOINT+11
CURLOPTTYPE_FUNCTIONPOINT=20000。因此CURLOPT_WRITEFUNCTION=20011
又另:
#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
define定义的宏内容与宏名完全相同,作用为:
用一个名称去编程、该是枚举的地方自动识别成枚举、该是宏的地方就自动识别成宏了
而且程序的可读性很好
简单点说枚举和宏的应用场合不同
就你这个例子
这么处理
你用一个名称去编程
该是枚举的地方自动识别成枚举
该是宏的地方就自动识别成宏了
而且程序的可读性很好
扩展:
为了实现跨平台,在C语言中,可以通过宏对已经存在的函数进行重新定义。
例如,在Windows中,具有itoa这个api函数用于数字转换为字符串:
#ifdef WIN32
#define itoa(intSource, strTarget) itoa((intSource), (strTarget), 10);
#else
#define itoa(intSource, strTarget) sprintf((strTarget), "%d", (intSource));
#endif
上面的宏定义中对Windows中的itoa函数进行了同名宏替换。
也就是说,在以后的编码过程中,itoa()中的参数只有两个,而不是原来的三个。
宏会替换掉原来的函数。
以下为转载
预编译(预处理或者预处理器处理)
预定义符号
define定义的宏和标识符
define定义的标识符
-
#define reg register
-
#define DO_FOREVER for(;;)
-
#define CASE break;case
define定义的宏
注意:
1).不应在宏定义的尾部加上分号(如果在宏定义的尾部添加分号会产生歧义,若在if ... else语句中更加明显)
2).在定义宏时宏名的后面不要添加空格,在使用时允许添加
3).在定义宏时尽量给变量添加圆括号,避免宏的副作用
-
#define _CRT_SECURE_NO_WARNINGS 1
-
#include<stdio.h>
-
#include<stdlib.h>
-
//带有副作用的宏
-
#define MAX(X,Y)((X)>(Y)?(X):(Y))
-
int main()
-
{
-
//int a=10,b=20;
-
//int ret=MAX(a++,b++); //((a++)>(b++)?(a++):(b++)) ((10)>(20)?(X):(21))
-
//printf("a=%d b=%d ret=%d\n",a,b,ret); //11 22 21
-
int a=20,b=10;
-
int ret=MAX(a++,b++); //((a++)>(b++)?(a++):(b++)) ((20)>(10)?(21):(Y))
-
printf("a=%d b=%d ret=%d\n",a,b,ret); //22 11 21
-
system("pause");
-
return 0;
-
}
宏和函数的优缺点
1).在代码长度角度上,因为宏是直接替换所以若宏较长会增加代码长度
2).在执行速度上,宏较函数快,因为函数存在调用/返回时的额外开销
3).在参数求值方面,define定义的宏可能会具有副作用会导致修改变量最后的值,而函数即使调用多次也不会修改变量原来的值
4).在参数类型方面,宏与类型无关,所以宏是可以传参数的而函数不行在C中函数是不可以传类型的
5).在是否可调试方面,宏不可调试,函数可调试
宏可以传类型的检测,实现malloc(动态开辟内存的函数)
#和##号
#:
使宏的参数不会被展开,转化为对应的字符串
##
将两个标识符连接起来;允许宏从分离的文本片中创建标识符
#define 定义一个预处理宏
#undef 取消宏的定义
#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配合使用,判断某个宏是否被定义 -
宏解析
1. ##操作符
##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号,它不能出现于宏替代表的开端和末尾。
例:
#define concat(s,t) s##t
#define AAA ABC
concat(A, AA)
将被替换成
ABC
2. 重新扫描和替换
在替换列表中的所有参数替换过之后,预处理器将对结果token序列重新扫描以便对其中的宏再次替换。
当正在替换的宏在其替换列表中发现自身时,就不再对其进行替换。今儿,在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换(防止递归)。
例:
#define ROOT AAA CCC
#define AAA ROOT
ROOT
将被替换成
ROOT CCC