【1】BUG简单示例代码

主要代码如下:

 #include <QCoreApplication>
#include <QDebug> #define ADD(a, b, c) ((a) + (b) + (c)) int func(int &n)
{
n += ;
return ;
} int addFunc(int a, int b, int c)
{
return (a + b + c);
} int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); // begin main procedure
int a1 = ;
qDebug() << "macro result :: " << ADD(func(a1), a1 + , a1);
qDebug() << "macro expanse result :: " << (() + ( + ) + ());
int a2 = ;
qDebug() << "function result :: " << addFunc(func(a2), a2 + , a2);
// end main procedure return a.exec();
} // run out:
/*
macro result :: 231
macro expanse result :: 31
function result :: 31
*/

注意:宏、宏展开、函数调用的结果差异。

用宏计算时,宏中的参数由前至后赋值。

逐步分析:调用func(a1),调用结束后,宏的第一个参数值为1(即函数返回值),同时由于func为引用形参,a1此时值为110;

宏的第二个参数值为a1 + 10 = 120;宏的第三个参数值为a1 = 110。最后,宏计算值为231(1 + 120 + 110)

假如把宏展开,第一个参数值为1;第二个参数值为10 + 10 = 20;第三个参数值为10;所以结果为31(1 + 20 + 10)

用函数计算,调用函数时,参数压栈由后向前。

逐步分析:函数第三个参数值为a2 = 10;第二个参数值为a2 + 10 = 20;

第一个参数值为函数返回值1,尽管函数调用结束后a2值为110,但参数二、三已压栈赋值完成。

【2】使用宏和函数的区别

使用宏,宏中的参数由前至后。

使用函数,函数调用时,参数压栈顺序由后向前。

更多关于宏的资料,请参见《宏定义学习

Good Good Study, Day Day Up.

顺序 选择 循环 总结

宏和函数的区别(一个BUG的总结)的更多相关文章

  1. C语言:带参数的宏与函数的区别

    带参数的宏和函数很相似,但有本质上的区别:宏展开仅仅是字符串的替换,不会对表达式进行计算:宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存.而函数是一段可以重复使用的代码,会被编译,会给它 ...

  2. 与number_format函数有关的一个bug?

    最近在做一个模仿excel功能的在线项目.其中有一个功能,数据列表中的数据,到了最后一列都要进行总计.这本来没什么难度.直接从数据库取出数据后,进行foreach相加就行 了.这是如此的简单,以至于用 ...

  3. C/C++之宏、内联函数和普通函数的区别

    内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算 ...

  4. [ 随手记 1 ] C/C++宏,普通函数,内联函数

    函数定义 C 语言中的函数定义的一般形式如下: return_type function_name( parameter list ) { body of the function } 在 C 语言中 ...

  5. js new一个函数和直接调用函数的区别

    用new和调用一个函数的区别:如果函数返回值是一个值类型(Number.String.Boolen)时,new函数将会返回这个函数的实例对象,而如果这个函数的返回值是一个引用类型(Object.Arr ...

  6. C++内联函数、宏定义和普通函数的区别

    C++内联函数.宏定义和普通函数的区别? 宏定义:在预处理阶段进行简单的文本替换,不会进行参数类型检查: 内联函数:在编译器的时候进行代码插入,编译器会在每次调用内联函数的地方直接将内联函数的内容展开 ...

  7. C语言带参宏定义和函数的区别

    带参数的宏和函数很相似,但有本质上的区别:宏展开仅仅是字符串的替换,不会对表达式进行计算:宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存.而函数是一段可以重复使用的代码,会被编译,会给它 ...

  8. NDK中使用pthread多线程中自己写的一个BUG

    在使用pthread进行NDK中的多线程开发时,自己写了一个BUG, void *darkGrayThread(void *args) { ThreadParam *param = (ThreadPa ...

  9. MySQL关于exists的一个bug

    今天碰到一个很奇怪的问题,关于exists的, 第一个语句如下: SELECT ) FROM APPLY t WHERE EXISTS ( SELECT r.APPLY_ID FROM RECORD ...

随机推荐

  1. VB改写C#

    1.VB的Val()函数 先从程序集中引入Microsoft.VisualBasic命名空间.不过,即便是引入了Microsoft.VisualBasic命名空间,还是不能直接使用像Val()这样的函 ...

  2. 重读《深入理解Java虚拟机》三、Java虚拟机执行的数据入口(类文件结构)

    1.Java如何实现平台无关系 Java要实现平台无关系就需要在Java代码和本地机器之间引入一个中间层,实现Java代码和本地机器的解耦,而这个中间层就是字节码.字节码独立于本地机器,以实现代码的可 ...

  3. 多点数据同步服务器sql汇总

    1. a表中是否存在c的列 IF COL_LENGTH('FeeType', 'ftName') IS NOT NULL select N'存在'as result ELSE select N'不存在 ...

  4. SSM(Spring+SpringMVC+Mybatis)框架环境搭建(整合步骤)(一)

    1. 前言 最近在写毕设过程中,重新梳理了一遍SSM框架,特此记录一下. 附上源码:https://gitee.com/niceyoo/jeenotes-ssm 2. 概述 在写代码之前我们先了解一下 ...

  5. (4.28)for xml path 在合并拆分上的作用演示

    for xml path 用于合并与拆分 1.合并 很多时候需要在SQL Server中创建逗号分隔列表.这可以使用SQL Server的DOR XML PATH功能完成.与select语句一起使用时 ...

  6. 20181220 Oracle程序包基本开发逻辑

    做事情,开始也许比较迷茫,也可能工具不会,也可能语言不会,但不要害怕 多去思考而不是盲目的开始工作,盲目的听从,程序开发都是不断训练自己的思维能力. 做每件事情都是有意义的,思考为什么这么做,这么做的 ...

  7. 20180310 KindEditor 富文本编辑器

    问题: 如何判断富文本编辑器文本内容非空 错误的办法,采用js 对控件本身的txt ID 号抓取获取值,由于加载富文本编辑器时,界面的ID 已经经过了修改或者可以用转换来说,所以抓取是无效果的. 需要 ...

  8. 下拉菜单被表单、图片、FLASH挡住的解决办法

    设置Flash的参数: <param name="wmode" value="opaque"> <object classid="c ...

  9. PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法

    一.数字补0. 如果要自动生成学号,自动生成某某编号,就像这样的形式“d0000009”.“d0000027”时,那么就会面临一个问题,怎么把左边用0补齐成这样8位数的编码呢?我想到了两种方法实现这个 ...

  10. Java 基础 引用数据类型 ArrayList集合

    引用数据类型(类) 分类 提到引用数据类型(类),其实我们对它并不陌生,如使用过的Scanner类.Random类. 我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Scanner类, ...