常量指针是指向常量的指针,指针指向的内存地址的内容是不可修改的。
即指针指向了一个常量,但是指针本身是一个变量
定义<code>const int *p=&a;</code>
这条语句告诉编译器,*p是常量,不能将*p作为左值进行操作。但这里的指针p还是一个变量,它的内容存放常量的地址,所以先声明常量指针再初始化是允许的,指针也是允许修改的
示例
1
2
3
4
5
指针常量是指针的常量,它是不可改变地址的指针,但可以对它所指向的内容进行修改。
即指针本身是一个常量,但是指着指向一个变量
指针常量定义<code>int * const p=&a;</code>
告诉编译器,p是常量,不能作为左值进行操作,但允许修改其指向的内容,即*p是可修改的。指针常量必须在声明的同时对其初始化,不允许先声明一个指针常量随后再对其赋值,这和声明一般的常量是一样的
如其名,不仅仅指针本身是一个常量(不可以修改其指向,指针指向的也是一个常量)
定义为<code>const int * const p = &ca;</code>
依据右左法则右左法则:首先从最里面未定义的标识符看起,然后先往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。(右左法则不是c标准里面的内容,它是从c标准的声明规定中归纳出来的方法。c标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的)
当然我们也可以依据编译原理的思想,来分析const修饰的语义
指针常量
定义
分析
char * const cp
右左法则
cp is a const pointer to character
语义
are neat
常量指针
const char * p;
char const * p
c++标准规定,const关键字放在类型或变量名之前等价的,c++里面没有const*的运算符
p is a pointer to const character;
const修饰的char *, 说明该指针指向的变量是一个常量
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
tcc的运行结果

gcc的运行结果
clang的运行结果
我们拿了大神法布里斯·贝拉(fabricebellard)的tcc与现代优化技术下的编译器的编译结果进行对比,我们可以很明显的发现。
我们所关注的是,一个不同支之处在于在现代优化技术下的编译器,相同的字符串变量在内存中只存储了一份, 字符数组除外,因为字符数组本身是一段连续存储的字符变量。
但是我之前上面的代码其实有点疑问,那就是<code>char * const pstr = "abcd"</code> 时候,我们的常理会认为pstr是一个指针常量,那么我么就应该不能修改其指向,但是可以修改其指向的字符串的值,但是结果真的如此么
我们从上面一个示例程序可以很明显的发现,pstr3和pstr4作为指针常量,指针本身的读写(主要是写)限制,是由编译器处理的,因此存在了栈区,但是字符串本身”abcd”却放在了代码段(或者说常量区)。那么我们可以大胆假设
1 指针常量本身的指向无法修改,这个由编译器在编译阶段进行检查
2 指针所指向的字符串也是无法修改的,因为字符串常量存储在代码段(或者常量区,因为有些分类中是不存在常量区的,常量区与代码段共同组成代码区)中,这段区域是由操作系统管理的只读段
回答的大神们都很好的回答了这个问题,把大家的答案总计一下大致说了这样一个意思
<code>char * const pstr = “abcd”</code> 这条语句是在定义常量时同时进行了初始化,那么初始化的变量就作为一个文本常量存储在了常量区。
我们来类比如下一条语句<code>const int a = 10;</code> 我们难道能够绕过a来修改变量本身的值10么,显然答案是否定的,当然和这条语句对比并不是很贴切,那么我们来看下面一条
因此请看下面代码
因此下面的代码无论const存在与否,都是在修改常量区的代码
必然导致访存错误,引起segmentfault
如果你非要这样做的话请使用
或者更复杂点
转载:http://blog.csdn.net/gatieme/article/details/48896847