const 与 #define 区别-程序员宅基地

技术标签: C语言  

这个区别用从几个角度来说:

角度1: 
就定义常量说的话: 
const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型。

角度2: 
就起作用的阶段而言: 
define是在编译的预处理阶段起作用,而const是在 编译、运行的时候起作用。

角度3: 
就起作用的方式而言: 
define只是简单的字符串替换,没有类型检查。而const有对应的数据类型,是要进行判断的,可以避免一些低级的错误。 
正因为define只是简单的字符串替换会导致边界效应,具体举例可以参考下面代码:

#define N 2+3 //我们预想的N值是5,我们这样使用N
double a = N/2;  //我们预想的a的值是2.5,可实际上a的值是3.5
  • 1
  • 2

角度4: 
就空间占用而言: 
例如:

#define PI 3.14     //预处理后 占用代码段空间
const float PI=3.14;    //本质上还是一个 float,占用数据段空间
  • 1
  • 2

角度5: 
从代码调试的方便程度而言: 
const常量可以进行调试的,define是不能进行调试的,因为在预编译阶段就已经替换掉了

角度6: 
从是否可以再定义的角度而言: 
const不足的地方,是与生俱来的,const不能重定义,而#define可以通过#undef取消某个符号的定义,再重新定义。

角度7: 
从某些特殊功能而言: 
define可以用来防止头文件重复引用,而const不能,可以参看下面代码:

//主要把以下代码放在头文件中,可以防止头文件被重复引用
#ifndef xxx//如果没有定义xxx
#define xxx//定义xxx

//这里是你的代码

#endif //结束如果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

PS: 下面说一下,头文件被重复引用的弊端: 
(1) 有些头文件重复引用只是增加了编译工作的工作量,不会引起太大的问题,仅仅是编译效率低一些,但是对于大工程而言编译效率低下那将是一件多么痛苦的事情。 
(2) 有些头文件重复包含,会引起错误,比如在头文件中定义了全局变量(虽然这种方式不被推荐,但确实是C规范允许的)这种会引起重复定义。

角度8: 
从某些复杂功能的实现的实现角度来看: 
使用define会使得代码看起来非常简单,而const无法实现该功能 
例如,MFC在实现六大核心机制中,大量使用了define 
1、MFC程序的初始化 
2、运行时类型识别(RTTI) 
3、动态创建 
4、永久保存 
5、消息映射 
6、消息传递

比如,在实现RTTI功能的时候,定义了如下宏,代码如下:

#define DECLARE_DYNCREATE(class_name) \

    DECLARE_DYNAMIC(class_name)\

    static CObject* PASCALCreateObject();
  • 1
  • 2
  • 3
  • 4
  • 5

最后做一下小结: 
从上面的各个角度,我们可以看到define和const直接的区别在某个点上同C语言与JAVA语言有一定的相似性,之所以这么说,原因如下: 
(1) JAVA中内部对象高度封装,比如对于内存的回收机制而言更是自动完成,不需要程序员多费心;而C语言中,每次我们用指针申请一段空间时,我们都需要仔细考虑,这个指针后面会不会还要使用,现在是不是可以释放了,会不会成为野指针等等问题,所有的内存相关问题都需要程序员自己考虑,但是好处是,C语言可以直接方便的操作内存,这是一把双刃剑,用得好事半功倍,用得不好,内存泄漏,指针跑飞,问题到处都是,就算抓到了dump,用windbg也不好分析(特别是跨模块的情况) 
(2) C语言和JAVA语言的差异点类比到define和const,我这里只是想强调define的作用非常强大,虽然它没有类型检测,不能调试,还要考虑边界效应,但是正因为没有类型检测,预编译是就完成,才使得它的使用更加灵活,功能更加强大,如果我们可以善用define,往往可以发挥到意想不到的效果。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26685237/article/details/79587445

智能推荐

第十一届蓝桥杯JavaB组试题H:走方格_java走方格试题-程序员宅基地

文章浏览阅读540次,点赞2次,收藏3次。试题 H: 走方格时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分【问题描述】在平面上有一些二维的点阵。这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。只能向右或者向下走。注意,如果行号和列数都是偶数,不能走入这一格中。问有多少种方案。【输入格式】输入一行包含两个整数 n, m。【输出格式】输出一个整数,表示_java走方格试题

vue3组件通信方式-程序员宅基地

文章浏览阅读1.1w次,点赞16次,收藏90次。vue3七种组件通信方式面试题经常会问到vue3组件间的通信方式,下文列举了七种常见的通信方式。propsemitv-modelrefsprovide/injecteventBusVuex4/pinia(vuex5)1. Props方式父组件以数据绑定的形式声明要传递的数据,子组件通过defineProperty()方法创建props对象,即可拿到父组件传来的数据。父组件的template中:<!-- list是我们要传递的数据 --><child-compo_vue3组件通信

Docker学习笔记(1)-centos7/ubuntu安装docker-程序员宅基地

文章浏览阅读150次。Centos7上安装dockerDocker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE。社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施、容器、插件等。社区版按照stable和edge两种方式发布,每个季度更新stable版本,如17.06,17.09;每个月份更新edge版本,如17.09,17.10。...

【C++】wav文件解析(兼容性强)_msdn wav c++_略游的博客-程序员宅基地

文章浏览阅读559次。最近将项目改为跨平台,于是音频模块从微软的XAudio2改用OpenAL库。之前使用MSDN的代码,所以现在改为了C++标准的写法,适用性更广。一开始本来在网上找代码,不过改了好几个都不是很好用。因为很多wav文件的fmt块后面并不是data块,经常还带有其他块,正确的方法应该是按MSDN的方法,找到data块再读取。..._msdn wav c++

dp求最大子段(一维数组,二维数组)_一维数组取最大段-程序员宅基地

文章浏览阅读588次。例如一位数组 ss[]={12,-4,-6,2,-4,8,-6,11,-3} 求子串最大值 非常简单的dp#include #include "string.h"int main(){ int ss[]={12,-4,-6,2,-4,8,-6,11,-3},dp[9],max=0; memset(dp,0,sizeof(dp));_一维数组取最大段

在linux下实现共享上网-程序员宅基地

文章浏览阅读708次。导读:   在linux下实现共享上网   转载时请注明出处和作者联系方式   作者联系方式:李先静   我的桌面机有两个网卡,一个连接天威的MODEN,一个连接笔记本电脑。笔记本电脑和桌面机之间共享数据没有问题,但笔记本电脑有时也要访问外网,怎么办呢?以前在桌面机上安装的Windows,要共享上网非常简单,把网络连接设置为共享就行了。现在安装了Fedora 7,按常规来看,实现共享上网

随便推点

公众号上的高分辨率数据(WorldView、Pleiades等)集中分享_公众号remote sensing dong_Remote Sensing_Dong的博客-程序员宅基地

文章浏览阅读4.4k次,点赞10次,收藏29次。年后新建了微信公众号,并分享了一些数据集,现整理出来集中进行共享,大家可以关注一下:A.WorldView高分辨率长时间序列数据集共享–适合变化检测、深度学习、信息提取原文地址:入口B.WorldView数据集Ⅱ–城市&乡村—适合建筑物提取、目标检测入口C WorldView数据集Ⅲ–多源数据QuickBird、WoldView、KOMPSAT3、建筑物矢量入口D 高分辨率SAR和光学数据集—TerraSAR&Pleiades数据分享入口E 多尺度机场目标检测数据集——_公众号remote sensing dong

vue 判断组件进入可视区域_vue 判断当前组件是否出现在可视范围内-程序员宅基地

文章浏览阅读4.7k次,点赞10次,收藏10次。1、mounted 监听 监听元素是否进入/移出可视区域window.addEventListener("scroll", this.scrollHandle, true); // 监听 监听元素是否进入/移出可视区域2、 methods 执行事件scrollHandle() { const offset = this.$el.getBoundingClientRect(); const offsetTop = offset.top; const off_vue 判断当前组件是否出现在可视范围内

为什么你的phpstorm安装xdebug不成功?_phpstorm无法加载xdebug-程序员宅基地

文章浏览阅读639次。不知道你在安装过程中是否发现,自己明明是跟着网上的教程来的,为什么会出现这些坑点?为什么就是不行?那当然是因为网上那些教程都tm是千篇一律复制粘贴过来的,有些既复杂还没用,没一个靠谱的。所以一个好的教程基本能解决大部分问题,比如这个PHP代码调试很难吗?最少配置使用xdebug不过还有一个问题,如图所示碰到报错,直接百度,结果百度了半天都没找到解决办法。实际上只要稍微认真看看报错信息就会发现,说是名字以及改了,还让你点这个链接查看,已经讲的很清楚了,点进去就能看到改成了什么名字比如这个xde_phpstorm无法加载xdebug

单位换算_一库伦等于多少千瓦时_貌若潘安的甜心超人的博客-程序员宅基地

文章浏览阅读2.4k次。单位换算千瓦时(kWh) 1千瓦时=1000×1瓦时=3600000焦耳 1千瓦时也就是俗话说说的一度电的能量;安时 (Ah) 1安时=(1库仑/秒)×3600秒=3600库仑,安时是电池常用术语,表示电池所储存的电量的多少;AH是衡量电池容量(电池量)的单位,其数值大小跟充放电电流大小有关系;KWH是衡量电池储存能量多少的单位.;能量(千瓦时KWh)= 电压(V)×电流(A )×时间(h);容量(安时Ah)=电流(安A)×时间(小时h);所以,容量(安时Ah)=能量(千瓦时KWh)/电压(V_一库伦等于多少千瓦时

Disruptor-03 共享与缓存-程序员宅基地

文章浏览阅读216次。什么是共享 下图是计算的基本结构。L1、L2、L3分别表示一级缓存、二级缓存、三级缓存,越靠近CPU的缓存,速度越快,容量也越小。所以L1缓存很小但很快,并且紧靠着在使用它的CPU内核;L2大一些,也慢一些,并且仍然只能被一个单独的CPU核使用;L3更大、更慢,并且被单个插槽上的所有CPU..._disruptor distribute cache

layui源码详细分析之树形菜单_layui 树形菜单-程序员宅基地

文章浏览阅读2.6w次,点赞2次,收藏8次。前言今天分析的是layui框架内置模块tree.js,该模块的功能是构建树形菜单,具体的形式(layui官网该模块的具体形式)如下: 自实现树形菜单使用html+css+js实现了树形菜单,具体的实现思路如下:html中定义包含树形菜单的容器节点规划好树形菜单的样式以及图标使用js构建html结构以及绑定事件,实现树形菜单的点击折叠实现效果图如下: 核心的实现是构建html结构,组织_layui 树形菜单