常量指针与指针常量

最近面试遇到了指针常量和常量指针,所以想整明白点

1、指针常量——指针类型的常量(int *const p)
本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。用法如下:

int a = 30,b = 20;
int * const p = &a;
*p = 30; // p指向的地址是一定的,但其内容可以修改

2、常量指针——指向“常量”的指针(const int *p, int const *p)
常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。用法如下:

int a = 10, b = 20;
const int *p = &a;
p = &b; // 指针可以指向其他地址,但是内容不可以改变

先来看下面四组

const int* p                      //p可变,p指向的内容不可变

int const *p                      //p可变,p指向的内容不可变

int* const p                      //p不可变,p指向的内容可变

const int* const p                 //p和p指向的内容都不可变

是不是感觉到了模糊,没事,教你一句口诀:左数右指

当const出现在*左边时,指针指向的数据为常量,也就是这个地址可以改变,

当const出现在*右边时,指针本身为常量,也就是p这个地址不变,但其指向的内容可变

下面来看几个例子

   

    int i = 0;
    
    const int* p1 = &i;
    int const* p2 = &i;
    int* const p3 = &i;
    const int* const p4 = &i;
    
    *p1 = 1;    // compile error根据左数右指,p1指向的数据为常量,所以无法修改
    p1 = NULL;  // ok根据左数右指,p1本身为变量,所以修改其保存的地址为空
    
    *p2 = 2;    // compile error同上
    p2 = NULL;  // ok同上
    
    *p3 = 3;    // ok根据左数右指,p3本身为常量,而其所指向内容可变,所以可以修改
    p3 = NULL;  // compile errorp3本身为常量,所以无法修改
    
    *p4 = 4;    // compile error根据左数右指,p4所指向的指不会改变
    p4 = NULL;  // compile error而且,p4本身也不会改变

再举栗子

    int main()

  {
    int m = 10;
    const int n = 20; // 必须在定义的同时初始化
 
    const int *pt1 = &m; //根据左数右指, 指针指向的内容为常量,不可改变,但指针本身可以改变
    int * const pt2 = &m; // 指针本身为常量,不可以指向其他的地方
 
    pt1 = &n; // ok,pt1本身为变量,所以地址可以修改
    pt2 = &n; // error,pt2本身为常量,所以无法修改
 
    *pt1 = 3; // error,但其指向内容为常量
    *pt2 = 4; // ok pt2所指向内容可以修改
 
    int *pt3 = &n; // error常量地址不能初始化普通指针,常量地址只能赋值给常量指针
    const int * pt4 = &n; // ok 根据左数右指,pt4为常量指针,用常量地址初始化常量指针
 
    int * const pt5; //error, pt5为指针常量,定义时必须初始化
    pt5 = &m; // error,指针本身为常量

    const int * const pt6 = &m; //pt5本身和pt5所指向内容均不可改变
    *pt6 = 5; // error不能改变内容
    pt6 = &n; // error不能指向其他地方
 
    const int * pt7; // ok,pt7为常量指针,
    pt7 = &m; // ok,指向内容为常量,但地址可以修改
 
    int * const pt8 = &n;//ok,pt8为指针常量,指向内容可变
    *pt8 = 8;//ok,pt8内容可修改
 
    return 0;
}

最后判断下面程序对错,并说明理由

int main()
{
    char * const str = "apple";
    * str = "orange";
    printf("%s\n",str);
    getchar();
}

错误

"apple"是字符串常量放在常量区,str指向"apple",那么str指向的是字符串常量"apple"的首地址,也就是字符a的地址,因此str指向字符a,*str就等于字符a,对*str的修改就是对字符串首字符a的修改,但"apple"是一个字符串常量,常量的值不可修改。

根据字符串赋值规则,可以修改整个字符串,方法是对指向字符串的指针str进行赋值,如下:

str = "orange";
但依旧是错误的,在该赋值语句中,系统会在常量区一块新的空间写入字符串"orange"并返回其首地址,此时str由指向字符串常量"apple"的首地址变为指向字符串常量"orange"的首地址,str指向的地址发生了变化,但str是指针常量不能被修改,所以错误。

如果想要程序编译通过,就不能将str声明为指针常量,否则str在初始化之后就无法修改。因此将const修饰符去掉,并修改字符串赋值语句,修改后程序如下:

int main()
{
    char * str = "apple";
    str = "orange";
    printf("%s\n",str);
    getchar();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值