C语言const修饰符探秘

前言

C语言是我接触的第一门程序设计语言,当时还很傻很天真,后来迅速被各种高级语言洗脑,但是不得不说,C的地位真的无可撼动。

const修饰符在C语言中很常用,但是最近读代码的时候常常搞不清楚,搜索了一番,做个总结。

整体认知

const是常量修饰符,代码中设法阻止变量被改变,这个时候可以使用const关键字。必须在声明const变量就初始化,因此,类似与这样的声明是错误的:
const int i;
i = 8;

编译器会报:error: assignment of read-only variable ‘i’。
我们必须要这样:
const int i = 8;

const修饰符的典型作用

  1. 最基本的,保护被修饰的作用,防止以外修改
  2. 编译器通常不为const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储和读取内存的操作,效率很高
  3. 使程序中的错误在编译的时候就被报出(因为2)。
下面会一一举例说明。

const修饰符的修饰对象探秘

修饰普通变量
const int i = 8;
int const i = 8;

上面两者是等价的,都是声明了一个值为5的常量。
修饰指针
const int *p;
int const *p;

上面两个是等价的,都声明了一个const int类型的指针,也就是说,程序里面不能改变*p的值,但是可以改变p的值(即可以改变指针的指向)。
int * const p = &n;

这个是声明了一个const的指针,const是修饰指针的。也即p的值不允许改变(指针就一定得指向n那块内存,不能改变p的指向),但是*p的值可以改变。
小技巧
  • const在*的左侧,const修饰指针所指的变量
  • const在*的右侧,const修饰指针本身

带const修饰的函数形参

首先要明确一点,非指针参数(值传递)传给函数的是参数的一份拷贝,本身就不会改变参数的值,所以加上const是没有意义的,例如:
#include <stdio.h>

void add(const int a)
{
        a = a + 1;
}

int main()
{
        int temp = 34;
        add(temp);
        printf("%d",temp);
        return 0;
}

虽然编译过不去,但是,就算不加const,在函数体中成功尝试修改了a,但是在本例中temp的值也是不变的,因为函数中修改的是a的一个拷贝(值传递)。
先看这个函数:
void foo(const int * p)
{
        *p += 1;
}

编译时就会报错,因为我们试图修改一个常量的值。
带const的形参是不允许在函数体内修改其值的(只读)。
不过一旦这样写就没辙了:
void foo(const int * p)
{
        int *r = p;
        *r += 1;
}

虽然编译器编译时会告诉你:warning: initialization discards qualifiers from pointer target type,说你赋值丢了一个属性修饰符,但是运行时还是可以改变p所指向内存的值。
再看这样一个例子:
void foo(int *const p1) {
    int a = 1;
    p1 = &a; 
}

显然编译不过去。这样做本来是想传进来一个const的指针,但实际上,这样是没有意义的。指针作为参数时也是传进去一个指针的拷贝。所以即使不加const,函数体中也是修改的这个“指针的拷贝”。这个函数实际上和本小节开头的例子是没区别的(但是这个指针的拷贝所指向的内容可是和被拷贝的东西是一样的)。
可以用下面的图说明:

和这个是类似的:



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值