[C语言]类型限定词const解析
作为C90增加的一个受限类型关键字,const赋予了它修饰的变量一个新属性——不变性,如果一个变量声明中带有关键字const,则无法通过赋值、增减运算来修改该变量的值。
一、指针与const结合
const与指针的结合较为复杂,因为我们需要把'让指针本身成为const'和'让指针指向的值成为const'区分开来。
1.1 int const *p
该声明表明我们声明了一个指针p,const在*左边,代表整个'*p'为不可修改的,也即p指向的值不可变。
- int a = 2;
- int b = 10;
- const int *p = &a;
- printf("%x %d\n",p,*p);
- *p = 4;
- printf("%x %d\n",p,*p);
尝试修改指针p指向的值,编译后报错:[Error] assignment of read-only location '*p',p指向的位置为只读。
修改一下a的值,看运行结果。

没有报错,a的值被成功修改。
再试一下,修改p的值:
- int a = 2;
- int b = 10;
- const int *p = &a;
- printf("%x %d\n",p,*p);
- // *p = 4; //[Error] assignment of read-only location '*p'
- p = &b;
- printf("%x %d\n",p,*p);
运行成功,由结果能看出,const的只读限制只对*p起作用,而p、p指向的对象的操作(a)都可读可写。
再看一个,将有const的指针赋值给没有const的指针:
- int a = 2;
- int b = 10;
- const int *p = &a;
- printf("%x %d\n",p,*p);
- int *p1 = &a;
- printf("%x %d\n",p1,*p1);
- p1 = p;
被const修饰的p与没有被修饰的p1值相同,指向位置的值也相同。不过在第九行'p1 = p;',弹出警告,继续运行:[Warning] assignment discards 'const' qualifier from pointer target type
1.2 int * const p
const在*右边,代表指针p不可修改,也即p总是指向同一个地址。
先修改个地址试一试。
- int a = 2;
- int b = 10;
- int * const p2 = &a;
- printf("%x %d\n",p2,*p2);
- p2 = &b;
第六行报错:[Error] assignment of read-only variable 'p2',p2为只读变量。
再折腾折腾,直接修改它指向的值,引用对象的值试试。

p2指向的地址都没变,只要不修改地址,其余的操作都可行。
1.3 const int * const p
第一个const表示p指向的值不可变,第二个const表示p本身不可变。也即p必须指向同一个位置,且所指位置存储的值也不可改变。
- int a = 2;
- int b = 10;
- const int * const p3 = &a;
- printf("%x %d\n",p3,*p3);
- a = 3;
- printf("%x %d\n",p3,*p3);
- //[Error] assignment of read-only variable '*p3'
- // p3 = &b;
- printf("%x %d\n",p3,*p3);
- //[Error] assignment of read-only location '*p3'
- // *p3 = 1;
- printf("%x %d\n",p3,*p3);
1.4 总结
当const与指针一同出现时,位于*左边的const使得数据成为常量,位于*const右边的const使得指针自身成为常量。更直白点来说就是:修饰谁,谁的内容就不可变,其余的都可变。
二、const与全局变量
由于程序的任何部分都可以修改全局变量的之,因此使用全局变量是一种很冒险的写法。但当我们用上了const后,这个问题就解决了。
2.1 extern
在一个工程中,如果我们在一个.c文件中声明了一个全局常量,在该工程其他文件中,对该全局常量的引用就需要使用关键字'extern'。
- /* file1.c---存放有全局常量的文件*/
- const int num = 100;
- /* file2.c---需要引用全集常量的文件*/
- extern const int num;
2.2 include与static
通过将全局声明放入头文件.h中,可以不必再纠结在哪个文件定义了声明、哪个文件引用了声明。不过需要注意的是,在声明时,const前必须加上static关键字,否则每一个引用该.h的文件都会得到该数据的一个副本,从而导致不同文件间的数据交流出问题。
- /*constant.h*/
- static const int num = 100;
使用头文件的缺点在于每一次引用.h都复制了数据,当.h中含有大量的数据时,就会引发新的问题了。
[C语言]类型限定词const解析的更多相关文章
- 类型限定词——const
类型限定词有三个:const volatile restrict. const:一般也叫常量修饰符. 作用:是修饰变量,被修饰的变量就变成常量了,不能被二次修改了. const int a=12:a ...
- java内存分配和String类型的深度解析
[尊重原创文章出自:http://my.oschina.net/xiaohui249/blog/170013] 摘要 从整体上介绍java内存的概念.构成以及分配机制,在此基础上深度解析java中的S ...
- 解剖SQLSERVER 第四篇 OrcaMDF里对dates类型数据的解析(译)
解剖SQLSERVER 第四篇 OrcaMDF里对dates类型数据的解析(译) http://improve.dk/parsing-dates-in-orcamdf/ 在SQLSERVER里面有几 ...
- WCF 已知类型和泛型解析程序 KnownType
数据协定继承 已知类型和泛型解析程序 Juval Lowy 下载代码示例 自首次发布以来,Windows Communication Foundation (WCF) 开发人员便必须处理数据协定继承方 ...
- C#匿名类型和动态解析减少定义传输类模板
C#作为强类型语言,在序列化和反序列化(json)场景中对字符串解析常常需要定义强类型模板,造成编码上的繁琐.其实可以使用匿名类型和动态解析减少json序列化时候的数据模板定义: string a = ...
- 变量和基本类型——复合类型,const限定符,处理类型
一.复合类型 复合类型是指基于其他类型定义的类型.C++语言有几种复合类型,包括引用和指针. 1.引用 引用并非对象,它只是为一个已存在的对象所起的另外一个名字. 除了以下2种情况,其他所有引用的类型 ...
- 【转】java内存分配和String类型的深度解析
一.引题 在java语言的所有数据类型中,String类型是比较特殊的一种类型,同时也是面试的时候经常被问到的一个知识点,本文结合java内存分配深度分析关于String的许多令人迷惑的问题.下面是本 ...
- c语言类型修饰符及内存
今天来学习一下c语言类型修饰符及内存分布 1.auto int a; 默认在内存 2.register int a; 限制变量定义在寄存器上的修饰符 编译器会尽量安排CPU的寄存器去存放这个a,如果寄 ...
- C语言类型(上)
前提说明 格式说明:以[signed] int 为例 表明该类型的完整表达是 signed int 只不过signed可以省略 所以 int 也代表 signed int 类型 signed和unsi ...
随机推荐
- hdu 2058 The sum problem(数学题)
一个数学问题:copy了别人的博客 #include<cstdio> #include<cstdlib> #include<cmath> int main() { ...
- 西邮Linux兴趣小组2014级免试挑战题
原文链接:西邮Linux兴趣小组2014级免试挑战题 又到了小组纳新的季节^_^,时间过的真快! 想起去年这会儿自己做免试题的时候根本找不着北@_@ 有幸今年能够在这里和大家分享免试挑战题,也正如我 ...
- java poi 获取单元格值时间
完整帮助类:JAVA poi 帮助类 /* * poi特殊日期格式:数字格式化成-yyyy年MM月dd日,格式 * */ private static ArrayList<String> ...
- 【NumberValidators】类库介绍
NumberValidators是一个用于验证中国大陆证件.号码是否符合国家标准的类库,因为该类库在昨日已经正式发布1.0.0版本至nuget,所以在此介绍下该类库的具体功能. NumberValid ...
- 构建NetCore应用框架之实战篇(三):BitAdminCore框架功能规划选择
本篇承接上篇内容,如果你不小心点击进来,建议从第一篇开始完整阅读,文章内容继承性连贯性. 构建NetCore应用框架之实战篇系列 一.BitAdminCore功能规划 如何选择框架的落地功能,前篇文章 ...
- F#语言入门之什么是F#语言
F#是一种函数式编程语言,可以轻松编写正确且可维护的代码. F#编程主要涉及定义类型推断和自动泛化的类型和函数. 这使您可以将焦点保留在问题域上并操纵其数据,而不是编程的细节. open System ...
- 网易云首席安全架构师谈安全新形势:DDOS两三天,游戏玩家数从几万降到几百
本文由 网易云发布. 安全是一个永恒的话题,在业务不断云化.攻击越来越复杂的当下,互联网安全呈现了出什么样的严峻形势?对这些形势,网易云又是如何应对的? 网易云首席安全架构师沈明星 4月13日,网易 ...
- 如何使用socket进行java网络编程(五)
本篇记录: 1.再谈readLine()方法 2.什么是真正的长连接 最近又参与了一个socket的项目,又遇到了老生常谈的readLine()问题:对方通过其vb程序向我方socketServer程 ...
- BS4爬取物价局房产备案价以及dataframe的操作来获取房价的信息分析
因为最近要买房子,然后对房市做了一些调研,发现套路极多.卖房子的顾问目前基本都是一派胡言能忽悠就忽悠,所以基本他们的话是不能信的.一个楼盘一次开盘基本上都是200-300套房子,数据量虽然不大,但是其 ...
- IntelliJ IDEA配置maven3.3.3+mybatis3.1.1
注:本文参考了孤傲苍狼关于MyBatis学习总结,在此表示感谢,原文链接为http://www.cnblogs.com/xdp-gacl/p/4261895.html. 1.新建project,勾选c ...