#define 的注意用法

在这里我们讲讲#define的一些误用,因为上一片已经讲了它的主要作用,这篇主要是一些比较常见的宏陷阱。首先轻松一下。如下的一个经典例子。

#define private public
#include
using namespace std;
class c
{
private:
 int i;
};

int main()
{
 c c1;
 c1.i=1;
 cout< <
}

#define 竟然让private如此的脆弱,但是却揭示了#define陷阱的根源,它仅仅是代码替换机制而已,除此之外,它什么都不是。

让我们步入正题,来看看下面的一个定义会产生一个什么样的错误?

#define f (x) ((x)-1)

如果这个是一个函数就没有什么问题
int f (int x) { return x-1; }

但是这里是define的世界,f(x)只见出现了一个可怕的空格
使得使得程序中如果出现了

f(10)

这个代码,最终就变成了

(10) (10-1)(10)这样一个奇怪的东西,当然这个代码倒是无法通过编译,还是可以检查出来的。算是让我们逃过了一次,下次就没有那么幸运了,让我们继续。

#define abs(x) x>0? x:-x (引用自C语言陷阱与缺陷)

这个代码有什么问题?也许大家也注意到了,我一直在用无数的()来写#define,不是因为我很喜欢()这个东西,而是当我在进行如下的调用的时候。

z = abs(a-b) //呜呼,这将产生什么东西呢?

答案是:

a-b>0? a-b : -a-b

这个显然不是我们要的结果,因为当a-b<0的时候将返回一个-a-b,要解决这个问题,我们就要使用()来解决。

#define abs(x) (x)>0? (x):-(x)

现在这个代码就可以正常的工作了。只要我们紧记#define是代码替换的机制,不要对它有任何的奢求,就会避免上面的问题。另外,因为宏不是一个类型,没有数据安全检查,在调试的时候也会产生障碍,所以,C++就一直提倡使用const和inline来替换#define,也许,#define真的会在历史的舞台上消失,但define在C语言时代留下的功绩却不应该忘记。

 

来自 http://community.youkuaiyun.com/Expert/topic/3195/3195102.xml?temp=.3936731

### C++ 中 `#define` 的使用方法 在C++编程中,预处理器指令 `#define` 主要用于定义宏替换。这种机制允许程序员创建常量或函数式的宏来简化代码编写并提高可读性和维护性。 #### 定义简单符号常量 通过指定名称和对应的替代文本可以创建简单的符号常量: ```cpp #define PI 3.14159265358979323846 ``` 上述语句表示每当源文件中的PI被编译器遇到时就会自动替换成后面的数值[^2]。 #### 带参数的宏定义 除了基本的值替换外,还可以定义带有一个或多参数的形式化宏表达式。这类似于内联函数的功能但是开销更小因为它们是在编译期间处理而不是运行期调用栈上执行: ```cpp #define SQUARE(x) ((x)*(x)) ``` 这里SQUARE接受单个输入变量x,并计算其平方;注意额外括号是为了确保运算优先级正确无误。 #### 使用连接符 ## 进行字符串拼接 当涉及到复杂的宏展开逻辑时,可能需要用到特殊的操作符如##来进行标记名粘连从而构建新的标识符: ```cpp #define CONCAT(a,b) a##b CONCAT(foo,bar); // 结果为foobar ``` 此例子展示了如何利用两个独立的部分组合成一个新的整体,在某些场景下非常有用比如动态生成类成员访问路径等场合。 #### 条件编译与防止重复包含头文件 为了控制特定部分代码仅在满足一定条件下才参与最终程序体合成过程之中,或者避免多次引入相同的内容造成冲突错误,则需借助于条件性的预处理命令配合`#define`一起工作: ```cpp #ifndef HEADER_FILE_H_ #define HEADER_FILE_H_ // Header file content here... #endif /*HEADER_FILE_H_*/ ``` 这种方式被称为保护声明(include guards),广泛应用于大型项目开发当中以保障系统的稳定可靠运作。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值