C语言中的const

const修饰的变量是只读的,本质还是变量

const修饰的局部变量在栈上分配空间

const修饰的全局变量在只读存储区分配空间

const只在编译期有用,在运行期无用

注意:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边。

总结:

C语言中的const使得变量具有只读属性

const将具有全局生命周期的变量存储于只读存储区

const不能定义真正意义上的常量!

C语言中只有通过enum定义的标识符才是真正意义上的常量。

编程实验

C/C++中的const

假设为test.c

 #include <stdio.h>

 int main()

 {

   const int c = ;

   int *p = (int*)&c;

   printf("Begin...\n");

   *p = ;

   printf("c = %d\n",c);      

   printf("End ...\n");

   return ;

 }

1)利用C编译器,即执行

gcc test.c

./a.out

得到C的值为5;

2)利用C++编译器,即执行

g++ test.c

./a.out

得到C的值是0,

说明第13行*p = 5 不起作用了。

同一个程序用C语言编译器和用C++编译器编译得到的运行结果不同。

下面再来修改程序,观察程序的运行结果:

 #include <stdio.h>

 int main()

 {

   const int c = ;

   int *p = (int*)&c;

   printf("Begin...\n");

   *p = ;

   printf("c = %d\n",c);
  printf("*p = %d\n",*p);
   printf("End ...\n"); 

      return ; 

 }

利用C编译器,得到

c = 5;

*p = 5;

利用C++编译器,得到

c = 0;

*p = 5;

为什么会这样呢?

说明了const关键字在从C语言到C++语言的进化中得到了很大的改变。那么变化究竟在哪里呢?

C++在C的基础上对const进行了进化处理

——当碰见const声明时在符号表中放入常量

——编译过程中若发现使用常量则直接以符号表中的值替换

——编译过程中若发现下述情况则给对应的常量分配存储空间(C++天生兼容C语言,也会有给常量分配空间的情况)

  对const常量使用了extern

  对const常量使用了&操作符

注意:

C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。(就是为了兼容C语言,兼容的意义就在于以前用C编译器编译过得程序,也能用C++编译器编译过,但运行的结果可能不同)

C语言中的const变量

——C语言中const变量是只读变量,会分配存储空间

C++中的const常量(从C语言中的只读变量变为一个常量了,但为了兼容C语言,可能为常量分配空间)

——可能分配存储空间

  当const常量为全局,并且需要在其他文件中使用

  当使用&操作符对const常量取地址

C++中的const常量类似于宏定义

——const int c = 5; 约等于 #define c 5

C++中的const常量在与宏定义不同

——const常量是由编译器处理

——编译器对const常量进行类型检查和作用域检查

——宏定义由预处理器处理,单纯的文本替换

const与宏的代码分析

 #include <stdio.h>

 void f()
{
#define a 3
const int b = ;
} void g()
{
printf("a = %d\n", a);
//printf("b = %d\n", b);
} int main()
{
const int A = ;
const int B = ;
int array[A + B] = {};
int i = ; for(i=; i<(A + B); i++)
{
printf("array[%d] = %d\n", i, array[i]);
} f();
g(); return ;
}

1)用C语言编译器进行编译,会发现出错。出错的地方在于:

int array[A + B] = {0};
虽然A与B是由const修饰的,根据上面所学的知识,A和B都是只读变量。数组的长度用两个变量相加,相加的结果到运行的时候才知道,
编译器就不乐意了,因此肯定会出错。

2)用C++编译器进行编译,就通过了。

此时A和B就是真正意义上的常量了。因此A+B也是常量

注意一个地方:

在g()函数中直接访问f()函数所定义的宏变量,结果没有出错,为什么?

因为宏是被预处理所处理的,直接进行文本替换,编译器压根不知道宏是什么,根本不知道宏的存在。其实,编译器看到的是这样的代码:

printf("a = %d\n",3);

说明宏是没有作用域的概念的。

在g()函数中调用

printf("b = %d\n", b);是不对的。

小结:

与C语言不同,C++中的const不是只读变量

C++中的const是一个真正意义上的常量

C++编译器可能会为const常量分配空间

C++完全兼容C语言中const常量的语法特性


进化后的const分析的更多相关文章

  1. C++解析(2):进化后的 const 分析

    0.目录 1.C语言中的const 2.C++中的const 3.对比 3.1 C语言与C++中的const 3.2 C++中的const与宏定义 4.小结 1.C语言中的const const修饰的 ...

  2. 第3课 进化后的 const分析

    1.  C语言中的const (1)const修饰的变量是只读的,使得变量具有只读属性,但本质还是变量.所以不是真正的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. (2)const修饰的局部 ...

  3. 第3课 进化后的const分析

    C语言中的const const修饰的变量是只读的,本质还是变量 const修饰的局部变量在栈上分配空间(改变这个空间的值,这个变量就会改变) const修饰的全局变量在只读存储区分配空间 const ...

  4. 第3课.进化后的const

    1.c语言中 const修饰的变量是只读的,本质上还是变量 const修饰的局部变量在栈上分配空间(因为在栈上分配空间,所以我们可以通过改变这个空间的值.间接去改变这个变量.) const修饰的全局变 ...

  5. C++ 成员函数前和函数后加const修饰符区别

    博客转载自: https://www.iteblog.com/archives/214.html 分析以下一段程序,阐述成员函数后缀const 和 成员函数前const 的作用 #include< ...

  6. [阿里DIEN] 深度兴趣进化网络源码分析 之 Keras版本

    [阿里DIEN] 深度兴趣进化网络源码分析 之 Keras版本 目录 [阿里DIEN] 深度兴趣进化网络源码分析 之 Keras版本 0x00 摘要 0x01 背景 1.1 代码进化 1.2 Deep ...

  7. [Reprint]C++函数前和函数后加const修饰符区别

    c++中关于const的用法有很多,const既可以修饰变量,也可以函数,不同的环境下,是有不同的含义.今天来讲讲const加在函数前和函数后面的区别.比如: 01 #include<iostr ...

  8. C++函数前和函数后加const修饰符区别

    class Test(){ public: Test(){} const int foo(int a); const int foo(int a) const; }; 一.概念 当const在函数名前 ...

  9. C++类的成员函数的形参列表后面的const

    看到(C++ Primer)类的成员函数这里,突然对成员函数形参列表后面的const感到迷惑. 因为书中开始说是修饰隐含形参this的,然后又说是声明该函数是只读的. 大为不解! 翻资料.找人讨论.. ...

随机推荐

  1. c# WF 第7节 对控件的基本操作

    本节内容: 1:修改控件的大小 2:控件的顺序 3:控件的对齐 4:移动button实例 1: 修改控件的大小 第一种: 第二种 : 一次操作多个控件: 选择一个控件.按住ctrl -- 再选择一个控 ...

  2. pycharm安装pymysql包

    1.为什么? 每个程序连接数据库,python开发2.*版本可以直接使用MySQL,python3.*版本需要下载使用PyMySQL包才能连接数据库... 2. 怎么做? 2.1. 更改源:pycha ...

  3. 关于destoon6.0下的ngnix伪静态

    关于destoon6.0下的ngnix伪静态配置 ##rewrite nginx rewrite '(.*)\.(asp|aspx|asa|asax|dll|jsp|cgi|fcgi|pl)(.*)' ...

  4. NOIP模拟赛 最佳组合

    题目描述 Description \(Bzeroth\) 大陆最终还是覆灭了,所以你需要为地灾军团服务了. 地灾军团军师黑袍不擅长写题面,所以你只需要看简化版的题意即可. 给定 \(3\) 个长度均为 ...

  5. hive中order by、distribute by、sort by和cluster by的区别和联系

    hive中order by.distribute by.sort by和cluster by的区别和联系 order by order by 会对数据进行全局排序,和oracle和mysql等数据库中 ...

  6. 全面理解UE4委托

    UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到通知,并进行相 ...

  7. Windows编译运行webrtc全过程

    年纪大了,不想写什么开头.摘要,咱直接开始吧. 不过首先还是要感谢声网提供的webrtc国内源码镜像. 首先,编译webrtc你需要一台win10,而且必须得是一直在更新版本的.因为编译过程需要用到c ...

  8. oracle中如何更改一个表的一个字段属性(名称,类型)

    修改字段的属性,名称方法 --修改某一个字段的类型,当该字段不为null时alter table 表名add 字段NUMBER(11,0) default 0 not null;--添加表一个字段 A ...

  9. Android系统之LK启动流程分析(一)

    1.前言 LK是Little Kernel的缩写,在Qualcomm平台的Android系统中普遍采用LK作为bootloader,它是一个开源项目,LK是整个系统的引导部分,所以不是独立存在的,但是 ...

  10. flexible.js 布局详解

    原文链接:http://caibaojian.com/flexible-js.html 本文讲的通过flexible.js实现了rem自适应,有了flexible.js,我们就不必再为移动端各种设备兼 ...