天天看点

C/C++中的const--常量指针与指针常量 问题解析 const进阶 疑问

常量指针是指向常量的指针,指针指向的内存地址的内容是不可修改的。

即指针指向了一个常量,但是指针本身是一个变量

定义<code>const int *p=&amp;a;</code>

这条语句告诉编译器,*p是常量,不能将*p作为左值进行操作。但这里的指针p还是一个变量,它的内容存放常量的地址,所以先声明常量指针再初始化是允许的,指针也是允许修改的

示例

1

2

3

4

5

指针常量是指针的常量,它是不可改变地址的指针,但可以对它所指向的内容进行修改。

即指针本身是一个常量,但是指着指向一个变量

指针常量定义<code>int * const p=&amp;a;</code>

告诉编译器,p是常量,不能作为左值进行操作,但允许修改其指向的内容,即*p是可修改的。指针常量必须在声明的同时对其初始化,不允许先声明一个指针常量随后再对其赋值,这和声明一般的常量是一样的

如其名,不仅仅指针本身是一个常量(不可以修改其指向,指针指向的也是一个常量)

定义为<code>const int * const p = &amp;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的运行结果

C/C++中的const--常量指针与指针常量 问题解析 const进阶 疑问

gcc的运行结果

C/C++中的const--常量指针与指针常量 问题解析 const进阶 疑问

clang的运行结果

C/C++中的const--常量指针与指针常量 问题解析 const进阶 疑问

我们拿了大神法布里斯·贝拉(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

继续阅读