#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏( defined macro) 。下面是宏的声明方式:

#define name(parameter-list) stuff

其中, parameter-list (参数列表)是二个由逗号分隔的符号列表,它们可能出现在stuff 中。参数列表的左括号必须与name 紧邻。如果两者之间有任何空白存在,参数列表就会被解释为stuff 的一部分。
当宏被调用时,名字后面是一个由逗号分隔的值的列表,每个值都与宏定义中的一个参数相对应,整个列表用一对括号包围。当参数出现在程序中时,与每个参数对应的实际值都将被替换到stuff中。

这里有一个宏,它接受一个参数:

#define SQUARE(x) x * x

如果在上述声明之后,你把

SQUARE ( 5 )

置于程序中,预处理器就会用下面这个表达式替换上面的表达式:

5 * 5

警告:

但是,这个宏存在一个问题。观察下面的代码段:

a = 5;
printf(" %d\n", SQUARE ( a + 1 ) );

乍一看,你可能觉得这段代码将打印36 这个值。事实上,它将打印11 。因为参数x 被文本a+l 替换,所以这条语句实际上变成了

printf("%d\n",a+1*a+1);

问题清楚了:由替换产生的表达式并没有按照预想的次序进行求值。
在宏定义中加上两个括号,这个问题使很轻松地解决了:

#define SQUARE(x) (x) * (x)

在前面那个例子里,预处理器现在将用下面这条语句执行替换,从而产生预期的结果。

printf("%d\n",(a+1)*(a+1));

=================================================

这里有另外一个宏定义。

#define DOUBLE(x)  (x) + (x)

定义中使用了括号,用于避免前面出现的问题。但是,使用这个宏,可能会出现另外一-个不同
的错误。下面这段代码将打印出什么值?

a = 5;
printf("%d\n" , 10 * DOUBLE( a ) );

警告:

看上去,它好像将打印100 ,但事实上它打印的是55 。再一次,通过观察宏替换产生的文本,
我们能够发现问题所在:

printf(" %d\n", 10 * ( a ) + ( a ) );

乘法运算在宏所定义的加法运算之前执行。这个错误很容易修正: 在定义宏时,你只要在整个表达式两边加上一对括号就可以了。

#define DOUBLE(x) ( (x) + (x) )

《C和指针》——宏中容易出现的错误相关推荐

  1. C语言指针学习中易犯的错误

    1.向null地址处copy数据 char *str = NULL; strcpy(str,"aaaaabbbbb"); 错误! NULL是操作系统保护的空间,不能往里面拷贝数据: ...

  2. C/C++常用宏定义,注意事项,宏中#和##的用法

    总结下宏和函数的不同之处,以供大家写代码时使用,这段总结摘自<C和指针>一书. 当然宏定义非常重要的,它可以帮助我们防止出错,提高代码的可移植性和可读性等. 下面列举一些成熟软件中常用得宏 ...

  3. 【转】C,C++宏中#与##的讲解

    转自:C,C++宏中#与##的讲解 - MoreWindows - 博客园 文中__FILE__与示例1可以参见<使用ANSI C and Microsoft C++中常用的预定义宏> 宏 ...

  4. C,C++宏中#与##的讲解

    文中__FILE__与示例1可以参见<使用ANSI C and Microsoft C++中常用的预定义宏> 宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing op ...

  5. C/C++宏中的#与##

    宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号. 如定义好#define STRING(x) #x之后, ...

  6. [c、c++]宏中#和##的用法(zz)

    http://blog.csdn.net/blackbillow/article/details/3850587 [c.c++]宏中"#"和"##"的用法(zz ...

  7. 【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针)

    什么是野指针? 指针变量存的地址是一块非法内存地址.进而形成野指针.但是需要注意一点,野指针不是NULL指针. 文章目录 1 野指针的概念 1.1 野指针代码案例初探 2 如何避免野指针 2.1 野指 ...

  8. 批量删除PPT第一页最后页——VBS脚本,在office宏中运行即可

    批量删除PPT第一页最后页--VBS脚本,在office宏中运行即可 Sub 批量删除第一页最后页() Dim ChangedCount As Integer Dim FileName As Stri ...

  9. Pointers on C - C 和指针 - 书中源代码

    Pointers on C - C 和指针 - 书中源代码 Kenneth A. Reek https://www.cs.rit.edu/~kar/index.html Pointers on C h ...

最新文章

  1. python3 zipfile_python3中zipfile模块的常用方法
  2. 三维点云的深度学习研究综述
  3. Qt中打开文件对话框和保存文件对话框
  4. 如何在我的世界里打造一台计算机,在《我的世界》里从零打造一台计算机有多难?...
  5. Npgsql 6.0.2 发布,赶紧升级!!!
  6. YIi 设置 ajax 验证
  7. create session 参数介绍
  8. 板绘如何厚涂?绘画时应该怎样厚涂?教你利用SAI结合数位板进行厚涂绘画!
  9. 用python算股票β系数_请教达人:Stata中计算多只股票月度beta系数的do文件怎么编写?...
  10. HTTP Live Streaming基础知识
  11. 欧拉函数与积性函数(互质数)
  12. CVPR2022Oral专题系列(一):低光增强
  13. Spring Cloud Alibaba阿里面试题
  14. jQuery——滚动条位置的获取与设置
  15. HP-UX Samba服务配置手册
  16. 三维实景应用制作工具有哪些?
  17. MySQL内连接、左外连接、右外连接
  18. 【数据库】数据库索引
  19. C语言指针 *p++和*++p及++*p的区别
  20. 查找统计python列表中的重复元素

热门文章

  1. pil对图像加透明 python_使用Python图像处理库Pillow处理图像文件
  2. 【转】c++优先队列(priority_queue)用法详解
  3. 最小二乘法移动最小二乘法
  4. tf.div()除法运算
  5. 汉诺塔问题的核心除了递归还有坐标系变换
  6. phpcmsV9单网页调用其他栏目文章 -方法总结
  7. html引入png不显示透明北京,解决在网页上显示PNG图片底色不透明的方法
  8. 递归生成数独java_[leetcode] 37. 解数独(Java)(dfs,递归,回溯)
  9. DTS-SHOP微信小程序多店铺商城平台java源码
  10. DOS批处理中%cd%和%~dp0的区别