const

  1. const意味着”只读”,欲阻止一个变量被改变,可以使用const关键字

  2. const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p)

define

#define指令有三种用法:

  1. 第一种是定义标识,标识有效范围为整个程序,形如#define XXX,常与#if配合使用

  2. 第二种是定义常数,如#define max 100,则max代表100(这种情况下使用const定义常数更好,因为:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误 )

  3. 第三种是定义”函数”,如#define get_max(a, b) ((a)>(b)?(a):(b)) 则以后使用get_max(x,y)就可以得到x和y中较大的数(这种方法存在一些弊病,如get_max(a++, b)时,a++会被执行多少次取决于a和b的大小!所以建议还是用内联函数而不是这种方法提高速度。虽然有这样的弊病,但这种方法的确非常灵活,因为a和b可以是各种数据类型。)。

const常量与define宏定义的区别

1. 编译器处理方式不同

  • define宏是在预处理阶段展开
  • const常量是编译运行阶段使用

2. 类型和安全检查不同

  • define宏没有类型,不做任何类型检查,仅仅是展开
  • const常量有具体的类型,在编译阶段会执行类型检查

3. 存储方式不同

  • define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存
  • const常量会在内存中分配(可以是堆中也可以是栈中)

4. 内存空间分配不同

  • const可以节省空间,避免不必要的内存分配

    #define PI 3.14159 //常量宏
    const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ……
    double i=Pi; //此时为Pi分配内存,以后不再分配!
    double I=PI; //编译期间进行宏替换,分配内存
    double j=Pi; //没有内存分配
    double J=PI; //再进行宏替换,又一次分配内存!
    const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝。

5. 提高了效率

  • 编译器通常不为普通const常量分配存 大专栏  const define static extern储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高

6. 宏替换只作替换,不做计算,不做表达式求解

  • 宏预编译时就替换了,程序运行时,并不分配内存

7. 总结

  1. 宏:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,”Hello world” 与 “world” 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大

  2. 变量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以被修改,在编译阶段会执行类型检查

  3. 常量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以根据const修饰的位置设定能否修改,在编译阶段会执行类型检查

  4. Constants should be declared as static constants and not #defines unless explicitly being used as a macro.

static

  1. 修饰局部变量:延长局部变量的生命周期,程序结束才会销毁;局部变量只会生成一份内存,只会初始化一次

  2. 修饰全局变量:只能在本文件中访问,修改全局变量的作用域,生命周期不会改,避免重复定义全局变量

  3. 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问

  4. 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内

  5. 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝

  6. 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量

extern

  1. 作用: 只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量

  2. 工作原理: 先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。

联合使用

  1. static与const作用:声明一个只读的静态变量;
    开发使用场景:在一个文件中经常使用的字符串常量,可以使用static与const组合

  2. 开发中使用场景:在多个文件中经常使用的同一个字符串常量,可以使用extern与const组合。
    static与const组合:在每个文件都需要定义一份静态全局变量。
    extern与const组合:只需要定义一份全局变量,多个文件共享。

const define static extern的更多相关文章

  1. const define static extern 关键词详解

    const const关键词并不能把一个变量变成一个常量, 在符号前加上const表示这个符号不能被赋值, 即他的值对这个符号来说是只读的, 但并不代表这个值不能用其他方法去改变. 通过下面的例子就能 ...

  2. C语言关键字—-sizeof 、typedef、const、static、register、extern、#define

    关键字:sizeof .#define.typedef.const.static.register.extern sizeof 1. 作用:求数据所占得内存空间大小 2. 本质:求数据得类型所占的内存 ...

  3. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  4. 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)

    李洪强iOS经典面试题155 - const,static,extern详解(面试必备) 一.const与宏的区别(面试题): const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽 ...

  5. iOS正确使用const,static,extern

    static 修饰局部变量 让局部变量只初始化一次 局部变量在程序中只有一份内存 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,这个局部变量才会销毁) 修饰全局变量 全局变 ...

  6. 如何正确使用const、static、extern

    转自:http://www.jianshu.com/p/2fd58ed2cf55 前言 本篇文章主要介绍在开发中怎么使用const.static.extern关键字. 一.const 与宏的区别: c ...

  7. const、static和extern的正确使用方式

    我们在看一些大牛的第三方时,里面会出现很多const.static和extern,尤其是const和static,const和extern的结合使用,直接令很多小伙伴懵逼了,今天就详细讲解一下这三个关 ...

  8. 《OOC》笔记(1)——C语言const、static和extern的用法

    <OOC>笔记(1)——C语言const.static和extern的用法 C语言中const关键字用法不少,我只喜欢两种用法.一是用于修饰函数形参,二是用于修饰全局变量和局部变量. 用c ...

  9. iOS 中 const static extern 关键字总结

    在看一些高手所写的代码时,总是可以看到我们小白平常不用的关键字,一次,两次,三次,不能总是不明不白,现在总结一下日常开发中常用的关键字的作用: 关键字const/static/extern的释义和用法 ...

随机推荐

  1. Linux-exec族函数

    1.为什么需要exec族函数 (1).fork子进程是为了执行新程序(fork创建子进程后,子进程和父进程同时被OS调度执行,因此子程序可以单独的执行一个程序,这样程序宏观上将会和父进程程序同时进行) ...

  2. MAC上的爬虫软件怎么选?看完这篇就够了

    在上一篇文章:网络爬虫软件哪个好用? 中,我们介绍了目前市面上比较成熟好用的网络爬虫软件, 但是其中有些不能在MAC上使用,因此今天这篇文章我们单独介绍一下在MAC操作系统中有哪些好用的爬虫软件,给大 ...

  3. JS 特效三大系列总结

    一. offset系列 1. offset系列的5个属性 1. offsetLeft : 用于获取元素到最近的定位父盒子的左侧距离 * 计算方式: 当前元素的左边框的左侧到定位父盒子的左边框右侧 * ...

  4. HDU重现赛之2019CCPC-江西省赛

    本人蒟蒻,5个小时过了5道,看到好几个大佬AK,%%%%%%% http://acm.hdu.edu.cn/contests/contest_show.php?cid=868 先放大佬的题解(不是我写 ...

  5. spring boot pom demo

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  6. linux下 c语言调用c++

    /*****************************g++编译cpp 文件为库文件.编译C文件时gcc 要链接 -l stdc++ 这个库**(非常重要)*///定义c++ class 头文件 ...

  7. sklearn包源码分析(二)——ensemble(未完成)

    网络资源 sklearn包tree模型importance解析

  8. How Cocoa Beans Grow And Are Harvested Into Chocolate

    What is Cocoa Beans Do you like chocolate? Most people do. The smooth, brown candy is deliciously sw ...

  9. The Five-Number Summary|Boxplots

    3.3 The Five-Number Summary; Boxplots the deciles divide a data set into tenths (10 equal parts), th ...

  10. 在Linux中#!/usr/bin/python之后把后面的代码当成程序来执行。 但是在windows中用IDLE编程的话#后面的都是注释,之后的代码都被当成文本了。 该怎么样才能解决这个问题呢?

    本文转自:http://bbs.csdn.net/topics/392027744?locationNum=6&fps=1 这种问题是大神不屑于解答,小白又完全不懂的问题... 同遇到这个问题 ...