• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C/C++中宏定义(#define)

C/C++中宏定义(#define)

作者:OlderDriver 字体:[增加 减小] 来源:互联网 时间:2017-05-28

OlderDriver 通过本文主要向大家介绍了c c++ c#区别,c和c++的区别,c语言和c++有什么区别,c/c++,c语言与c++的区别等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利。

宏的定义在程序中是非常有用的,但是使用不当,就会给自身造成很大的困扰。通常这种困扰为:宏使用在计算方面。

本例子主要是在宏的计算方面,很多时候,大家都知道定义一个计算的宏,对于编译和编程是多么的有用。现在定义有以下一个计算 “乘法” 的宏。

#include <stdio.h>
#define MUL(a) ((a)*(a)*(a))
int main(int argc,char *argv[])
{
 int i = 10;
 int sum = MUL(i);
 printf("MUL(%d) = %d\n",i,sum);
 return 0;  
}
</stdio.h>
</div>

  上面程序的这种做法对于非负数而言那就是没有问题的,比如,程序中的 变量 i=10,这个时候,调用宏得到的数据如下:

  但是如何变量的数值是自加或者自减的操作的话,结果就不一样了。

  假如我们将上面的程序变为下面这样的

#include <stdio.h>
#define MUL(a) ((a)*(a)*(a))
int main(int argc,char *argv[])
{
 int i = 10;
 int sum = MUL(++i);
 printf("MUL(%d) = %d\n",i,sum);
 return 0;  
}
</stdio.h>
</div>

  得到的结果并不是 11 * 11 *11 = 1331这个数据,而是 1872,这时候有人会问为什么?

  得到宏的朋友或者了解过宏在计算方面的朋友就会知道,这除了是宏的问题,还是本身程序员编写这段代码的问题。当使用了 ++i 和 i++ 的时候,

要特别注意在宏中是全部使用 ++i或者i++的,变成的格式如下

MUL(i++) ((i++)*(i++)*(i++))
 MUL(++i) ((++i)*(++i)*(++i))
</div>

  上述的做法显然不是我们想要的计算结果,可能在我们程序中看到的是MUL(++i) 或者 MUL(i++),认为实际上是如下情况:

//当i的初始化数值为10的时候,进行i++的 MUL(i++)宏计算,即是:int i = 10;
//MUL(i ++)的数值计算结果相比是 10 * 11 * 12的,这是没有问题的,但是 i的值呢??是11吗??显然不是。    MUL(i++) = 10 * 11 *12;i = ??;

  i的数值如下图所示

  诚然,i的数值变成了 13,这是为什么呢??

  那就是因为这个MUL(a)这个宏和程序员的 “自加自减” 操作所造成的。这里先普及一下 C/C++语言的 “自加自减” 操作:

//自加自减的操作

i++ 和 ++i  ----> 这里的操作属于++后操作,可以替换成 i = i+1 的结果。                   

    但是,当它赋值给一个变量的时候,表示的内容和含义就有不同: (假设i = 10)

    1.  sum1 = i++;

    2.  sum2 = ++i; 

    1中的sum1的数值就是 10, i为 11

    2中的sum2的数值就是 11, i为 11

这是因为:

    i++ 操作是 先赋值给 sum1后,自己在执行 i = i+1的操作

    ++i 操作是 先进行 i = i+ 1的操作,然后再赋值给sum2 

这样得到的结果当然不同了,但是i最终的结果是要加1的,只不过是赋值给变量的时候会有不同

  通过对自加自减的操作进行说明,不知道大家是否明白为什么了吗??

当 i  = 10的时候,MUL(i++)就是为  (i++)*(i++)*(i++)的计算结果,考虑到C/C++的运算符结合性, 

先计算第一个 i++,这是一个先计算后赋值的自加方式,那么这是后第一个 (i++)的数值待定为 10 ,那么第 

二个的i是因为第一个数据的 (i++)起了作用而变化的,这时候第二个(i++)的数值为11,然后加1,这时候 根 

据结合性,先计算前面两个数据,就是(i++) * (i++)的数值了,即为:10 * 11了,这时候的i数值是 12; 

然后计算第三个 i++的数值,这时候第三个i++中的i数值为 12,计算后再加1,也就是说,10 * 11 * 12之后,

i= 12 的数值在进行i++变为 13了。所以  MUL(i++) = 10 * 11 * 12 = 1320。   

  另外,在进行++i的操作和上述的情况差不多,只不过是先做自加的运算,在进行赋值。

当 i = 10的时候,MUL(++i)实际上也为 (++i)*(++i)*(++i)的方式,这时候先计算第一个 (++i),这是一 

个先计算后赋值的结合方式,那么 i = i+1 = 11;这时候准备计算第二个(++i)的时候,因为需要先计算后赋值, 

所以 第二个 ++i 之后的数值为12,但是因为i属于同一个变量和属性,那么第一个i也会变成 12了,这时候结合性

考虑应该是计算前两个(++i)的结果,再与第三个(++i)计算,即(++i)*(++i) = 12 * 12;然后,我们计算第三个 

(++i)的数值,由于前面第二个++i的i值,所以第三个++i即为 13,此时,12 * 12 * 13。  

  有人可能顾虑,为什么最后不是13 * 13 * 13的呢?那不是最后都是13吗??  ------》其实这种想法是错误的,

这必须先理解运算符的结合性。我们知道,当计算中遇到了括号的时候,我们先计算括号的内容,这是我们在数学中的惯性思维。但是对于计算机而言,计算机必须 有计算的优先级,也就是运算符的优先级问题。首先我们计算前面两个括号的内容,以为两个括号之间有乘号(*),所以计算前面两个(++i)之后,必须进行乘法计算,这就是优先级中的乘法计算,自左向右计算。所以结果变为了 12 * 12的最终结果在和第三个括号的(++i)计算,就是144 * (++ i) = 144 * 13;

   所以MUL(++i)的结果如下:

总结:

  慎用宏在计算方面的,但是宏的有点还是很多的,对于C语言来说,宏可以减少运行的时间。在C++中,宏由于不会对类型进行检查,安全性不够,所以建议使用const来

进行使用,这样可以保证类型一致。这是C/C++对宏的严谨性进行优化的结果。

以上所述是小编给大家介绍的C/C++中宏(#define)定义知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C/C++ 中堆和栈及静态数据区详解
  • C/C++中运算符的优先级、运算符的结合性详解
  • C/C++ 中sizeof('a')对比详细介绍
  • C/C++中的typedef和#define详解
  • C/C++中宏定义(#define)
  • C/C++函数参数传递机制详解及实例
  • C/C++ 公有继承、保护继承和私有继承的对比详解
  • C/C++静态类和this指针详解及实例代码
  • C/C++中提高查找速度的小技巧
  • C/C++ ip地址与int类型的转换实例详解

相关文章

  • 2017-05-28深入理解约瑟夫环的数学优化方法
  • 2017-05-28MySQL的C语言API接口
  • 2017-05-28纯C语言:分治快速排序源码分享
  • 2017-05-28C/C++中提高查找速度的小技巧
  • 2017-05-28C++中字符串以及数组和指针的互相使用讲解
  • 2017-05-28深入linux下遍历目录树的方法总结分析
  • 2017-05-28websocket++简单使用及实例分析
  • 2017-05-28详解C++设计模式编程中责任链模式的应用
  • 2017-05-28C++实现单链表删除倒数第k个节点的方法
  • 2017-05-28关于统计数字问题的算法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • linux下C语言中的mkdir函数与rmdir函数
    • C语言 结构体(Struct)详解及示例代码
    • 简单总结C++中的修饰符类型
    • 解析C++中四种强制类型转换的区别详解
    • c++中冒号(:)和双冒号(::)的使用说明
    • 关于C/C++中可变参数的详细介绍(va_list,va_start,va_arg,va_end)
    • C++通过自定义函数求一元二次方程的根
    • C语言中的BYTE和char深入解析
    • 浅析结束程序函数exit, _exit,atexit的区别
    • C++位运算符详解(异或运算符和移位运算符)

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有