基于C中含有if的宏定义详解_C 语言

含有if的宏定义
当宏定义中含有 if 时
1) 定义如下宏
#define DC(p) if( foo(p) )fun(p)
用在下面的环境中
if(k>n)
DC(k);
else
DC(n);
宏替换后,如下
if(k>n)
if( foo(k) )
fun(k);
else
if( foo(n) )
fun( n );
可见, 原来的 if 和 else 不再配对.
2) 为了避免这类问题, 我们可以将包含if语句的宏定义为一个整体.
#define DC(p) {if( foo(p) ) fun(p);}
但是, 替换后变为
if(k>n)
{
if( foo(k) )
fun(k);
};else ...
由于else前面多了个分号, 编译时会提示错误没有与else配对的if.
3)因为这些原因, 在宏定义中, 经常会将语句序列放入 do{...}while(0)块中.
如下
#define DC(p) do{( if( foo(p) ) fun(p); }while(0)
替换后
if(k>n)
do
{
if( foo(k) )
fun(k);
}while(0);
else
...
程序可以正常运行
4)替换方案
a)采用 ? : 表达式
#define DC(p) ( (foo(p)) ? (fun(p)):0)
b)利用布尔运算的短路径求值属性
#define DC(p) ( (foo(p)) && (fun(p), 1) )
参考书籍: <<代码阅读方法与实践>>

时间: 2024-11-03 16:44:40

基于C中含有if的宏定义详解_C 语言的相关文章

基于C++中常见编译错误的总结详解_C 语言

在日常编码过程中会遇见各种编译错误,本文对常见的编译错误进行分析总结.(基本的编译错误在这里不列举,后续后持续更新) 1.error c101008a解决方法该错误出现在项目升级过程中会出现,比如说项目从vs2008升级到vs2010.解决办法:在项目上点右键,清理(Clean),重新编译,问题解决 2.error C2252解决方法该错误主要在项目从vs2008升级到vs2010出先.error C2252: an explicit instantiation of a template ca

C++中auto_ptr智能指针的用法详解_C 语言

智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足以涵盖auto_ptr的大部分内容. auto_ptr是什么? auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者.当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有

解析c++中的默认operator=操作的详解_C 语言

在c++中,如果没有定义operator=操作,编译器会提供一个默认的operator=操作.由于operator=操作和拷贝构造函数的功能类似,都执行拷贝操作.因此,编译器也分提供无用的默认operator=操作和非无用的默认operator=操作.并且什么时候提供非无用的默认operator=操作和无用的等操作的情形也和拷贝构造函数类似.(详细分析过程请参考<基于c++中的默认拷贝函数的使用详解>) 对于一个类,编译器会提供非无用的operator=操作的情形: 1 该类是含有虚成员函数(

C语言中改变目录的相关操作函数详解_C 语言

C语言fchdir()函数:改变当前工作目录头文件: #include <unistd.h> 定义函数: int fchdir(int fd); 函数说明:fchdir()用来将当前的工作目录改变成以参数fd 所指的文件描述词. 返回值:执行成功则返回 0, 失败返回-1, errno 为错误代码. 范例 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <

C++中Boost库裁剪与其应用详解_C 语言

前言 Boost 库涵盖的范围极广,有字符串和文本处理相关子库比如 format 库和 regexp 库,有容器相关子库比如 variant 库(和 Qt 的 QVariant 有得一拼),有迭代器子库比如 tokenizer 库(可以把字符进行 tokenize),还有算法.函数对象和高阶编程相关子库如functional 库.lambda 库和 signal 库,还有泛型编程.模板编程子库如 call traits.mpl,还有并发编程相关的 thread 库,等等等等. Boost 是如此

基于C++ map中key使用指针问题的详解_C 语言

C++实际开发的过程会经常使用到map.map是一个key-value值对,key唯一,可以用find进行快速的查找.其时间复杂度为O(logN),如果采用for循环进行遍历数据时间复杂度为O(N).如果map中的数据量比较少时,采用find和for循环遍历的效率基本没有太大的区别,但是在实际的开发过程中,存储在map中的数据往往是大量的,这个时候map采用find方式效率比遍历效率高的多. 确定采用find方式查找数据后,我们需要考虑存储map的空间复杂度,对于基础数据类型的数据(int ch

VC中BASE64编码和解码使用详解_C 语言

BASE64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本.完整的BASE64定义可见 RFC1421和 RFC2045.编码后的数据比原始数据略长,为原来的4/3.在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行. 转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位.数据不足3byte的话,于缓冲区中剩下的Bit用0补足.然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXY

深入线性时间复杂度求数组中第K大数的方法详解_C 语言

求数组中第K大的数可以基于快排序思想,步骤如下:1.随机选择一个支点2.将比支点大的数,放到数组左边:将比支点小的数放到数组右边:将支点放到中间(属于左部分)3.设左部分的长度为L,当K < L时,递归地在左部分找第K大的数当K > L时,递归地在有部分中找第(K - L)大的数当K = L时,返回左右两部分的分割点(即原来的支点),就是要求的第K大的数以上思想的代码实现如下: 复制代码 代码如下: /**线性时间复杂度求数组中第K大数** author :liuzhiwei ** data 

基于稀疏图上的Johnson算法的详解_C 语言

算法步骤简述: 1.计算图G加入新结点后的图G',加入的新结点0到所有原结点之间距离为0,同时形成新的边集E': 2.使用Bellman-Ford算法处理G',并形成0结点到各结点的最小距离d. 3.如果Bellman-Ford算法检测出有负权回路则提示FALSE并退出,否则继续. 4.对所有G'中的顶点v,根据0结点到v的最小距离,将h(v)设置为这个值. 5.对所有的边w(u,v),权值更新为w(u,v)+h(u)-h(v) 6.对图G中所有结点运行Dijkstra算法计算与其他顶点最短距离