1、(decltype(x)) 为什么要有最外层的这个括号,意义是什么,不加会怎么样?
(首先我大概介绍一下我现在对这个宏的理解,为了在不同环境中使用decltype,他自己定义了DECLTYPE,并且从63行开始通过自己实现decltype的功能,decltype在C++中的功能与auto近似,此处具体是什么我不确定)
2、第一个define后面什么都没跟是什么意思 一般define不是像 #define PI 3.14 这种后面会放一个东西跟着的吗(如例子里PI后面跟着3.14)
3、73行等号左右两边的dst为什么要加括号?不加会怎么样?还是说这是什么书写标准吗?
4、65 66 67等行的末尾有一个 \ 符号,这个符号是什么意思,有什么作用。
5、66和72行的两个do while具体实现了什么功能,大致讲解一下怎么实现的。
1、宏外面加括号看情况而定,有些情况可以加,也可以不加,需要考虑实际的使用环境,比如定义一个宏
#define SUM(a, b) a + b
#define SUM(a, b) (a + b)
// 这里的话肯定是建议加括号的,因为宏在编译的时候会替换到程序中,如果程序里面写 int s = 2 * SUM;
// 将宏替换过来就是 int s = 2 * a + b; 和 int s = 2 * (a + b); 两种情况,很明显第二种是正确的,所以这种情况的话就必须要加括号
2、define DECLTYPE(x) 只有宏名,没有值,这种语法也是可以的,主要作用用于条件编译,比如常用的手段就是判断某标识符是否被#define定义过。
3、73行等号左右两边的dst为什么要加括号,这个跟第1点介绍的一样,加了括号可以把 dst 作为一个整体,因为在传递参数进来的时候,dst可能由表达式组成,不加括号有可能造成歧义,所以为了保险起见就加上括号。
4、末尾有一个 \ 符号是语句换行连接的意思,比如65 ~ 68行的语句本来是写在一行的,像这样子 #define PI 3.14,但是为了可读性、美观,就换行书写了,使用 \ 符号作为换行连接的作用。
5、65和71行的宏定义实体就是 66和72行的两个do while函数块。
习惯问题,加上更安全保险
宏定义有陷阱 注意
1、(decltype(x)) 为什么要有最外层的这个括号,意义是什么,不加会怎么样?
--> 先要清楚宏在编译的时候是无脑展开的,对于这个表达式 decltype(x) 到底展开是怎么样的很难判断,所以加个括号消除歧义和未知结果,比如 define decltype(x) x=1 ,对于代码里面这样使用 decltype(x) * 2 展开后变成了 x=1 * 2,显然是错了的
2、第一个define后面什么都没跟是什么意思 一般define不是像 #define PI 3.14 这种后面会放一个东西跟着的吗(如例子里PI后面跟着3.14)
--> decltype(x)(空)这里明显是为了如果代码里面有使用这个宏就直接是空的代替,没有任何展开代码。这种是经常用的,比如代码 SEM_TAKE(x);a++;SEM_GIVE(x); 实现先拿锁,然后在加1,然后在释放锁。 但是在一些时候单进程里面根本不需要锁,所以可以直接定义 #define SEM_TAKE(x) (空), 这样代码不需要修改,可以很好的保持一致性。
3、73行等号左右两边的dst为什么要加括号?不加会怎么样?还是说这是什么书写标准吗?
--> 加个括号消除歧义和未知结果,建议稍微复杂点的宏加上括号
4、65 66 67等行的末尾有一个 \ 符号,这个符号是什么意思,有什么作用。
--> \ 表示一个宏定义了多行,如果没有\ ,这个宏定义后面的内容只能写到一行,不然会编译错误。 定义多行后宏展开用所有的这些行代替
5、66和72行的两个do while具体实现了什么功能,大致讲解一下怎么实现的。
--> 先说下do while(0),这是一个语法糖,可以让代码看起来是一个整体,并且很多时候可以代替goto的功能
这里实现的功能是:dst和src是两个char *的变量,这里实现很简单就是 dst = src 这个操作。也可以在代码里面搜索下它在哪里用的
char ** _da_dst = (char ** )(&dst); //定义了个char二维指针 指向了dst的地址
*da_dst =(char *)src; // 取二维指针的值指向了dst的地址,然后把src赋值给dst