zoukankan      html  css  js  c++  java
  • 关于const和define的内存分配问题的总结

    关于const和define的内存分配问题

    const与#define宏定义的区别----C语言深度剖析

    1,  const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝。

    2,  #define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。

    3,  #define宏没有类型,而const修饰的只读变量具有特定的类型。

    总结:const节省了空间,避免了不必要的内存分配,同时提高了效率。编译器通常不为普通的const只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。C++中是不太推荐用宏的,尽量少用.因为C++是强类型的语言,希望通过类型检查来降低程序中的很多错误,而宏只是在编译期前做简单替换,绕过了类型检查,失去了强类型系统的优势支撑。

    例如:

    #define M 3   //宏常量

    const int N=5;  // 此时并未将N放入内存中

    ..............

     

    int i=N;  //此时为N分配内存,以后不再分配!

    int I=M;  //预编译期间进行宏替换,分配内存

    int j=N;  //没有内存分配

    int J=M;  //再进行宏替换,又一次分配内存!

    原因:const定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以const定义的只读变量在程序运行过程中只有一份拷贝。

    在c++我们知道一般是采用const来进行替代#define的。

    例如:

    const int N=3;//注意采用的是赋值的形式并且末尾有分号

    #define N 3

    特殊情况

    在C中我们知道#define进行预定义的某个数是被分配内存的,其文件在编译预处理过程中就会用定义好的数据去替代文中的符号。

    但是const却是不一样的,一般情况下编译器也是不为const创建空间的,只是将这个定义的数字保存在符号表中的。但是在下列几种情况下编译器会为const定义的常量分配内存的。

    1. 1.       使用了extern

    extern const int N=3;

    因为使用了extern我们将可能在外部文件使用N,而const默认的是内部链接,所以我们必须要为之分配内存的。

    1. 2.       取地址操作

    #include<iostream>

    using namespace std;

    const int M=3;

    int main()

    {

           const       int *p=&M;

           //当编译器发现有对const定义的常量进行取地址操作时候会对M进行内存分配,

           //注意这个地址是const int*类型的,地址中的内容不可以改变的

           int *pp=(int*)(&M)

           //此处我们将const int*类型强制转化成int * 但是对于*pp的任何赋值操作还是会报错的,

           //因为本质上的M是常量不可改变的,这也是const的优点

           cout<<*p<<endl;   

     

           return 0;

    }

    1. 3.       const定义的常量未知的时候,这是#define无法实现的。

    #include<iostream>

    using namespace std;

    int main()

    {

           const int b=cin.get();//此处const定义的b是未知的所以要为它分配内存,但是一旦分配就不可以改变的。

           //但是如果读者此处想在利用未知的const常量来定义数组还是会报错的。

           //即int array[b]是不行的,因为编译器在从上往下走的时候是要确定数组的大小的

           //但是采用new操作就不会报错的int *array=new int(b);

     

           cout<<b<<endl;

           return 0;

    }

  • 相关阅读:
    CSS实现点击改变元素背景色
    php三种方法从控制结构或脚本中跳出
    如何关闭运行在某端口的的进程,例如 :8080端口
    Webpack简易入门教程
    git add -A 和 git add . 的区别
    怎样把已经做好的网页传到网上去?
    jquery源码之事件系统-- jQuery.event
    jquery源码之缓存系统--$.data
    jquery源码之延迟对象--Deferred
    jquery源码之低调的回调函数队列--Callbacks
  • 原文地址:https://www.cnblogs.com/lxd2502/p/4572368.html
Copyright © 2011-2022 走看看