C语言const关键字到底怎么用

前言

作为C/C++开发人员,我们看到关键字const时,第一反应就说它就是:只读。const要求其所修饰的对象为常量。不可对其修改和二次赋值操作(不能作为左值出现)。本文说明C中的const关键字,不包括C++。

const基本介绍

const是constant的简写,可以理解成是”只读变量“的限定词,从这里可以看出,const修饰的是变量,跟常量是不同的,常量是被编译器放在内存中的只读区域,当然也就不能够去修改它。

而”只读变量“则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。

const就是用来限定一个变量不允许被改变的修饰符。因为const声明的变量是只读变量。

用const修饰普通变量

例如:

const int NUM = 10; //与int const NUM等价
NUM = 12;  //编译错误,不可再次修改

以上代码中的const告诉编译器,const修饰NUM是只读,不可以被修改。如果在函数中不小心使用类似二次赋值操作,编译器会捕获这个错误,并生成一条错误的信息。类似提示向只读变量‘NUM’赋值:

这里要注意一下

如果需要使用const修饰一个变量,那么它只能在开始声明时就赋值,否则后面就没有机会了。

修饰数组

#include <stdio.h>

int sum( int arr[],int n);

int main(int argc, char const *argv[])
{
	 int arr[] = {0,0,2,3,4}; //

	arr[2] = 1; // 0 + 0 +1 + 3 + 4

	int value = sum(arr,5);

	printf("ar value: %d\n",value); // 8


	return 0;
}


int sum( int arr[],int n){

	int i;
	int total = 0;

	for (i = 0; i < n; i++){
		total += arr[i];
	}

	return total;
}

编译运行:

在这里插入图片描述
编译运行一点问题都没有,如果使用const关键字修饰数组,使其元素不允许被改变。

const int arr[] = {0,0,2,3,4}; //与int const arr[]等价
arr[2] = 1; //编译错误

试图修改arr的内容的操作是非法的,编译器将会报错:

在这里插入图片描述
修饰指针

修饰指针的情况比较多,主要有以下几种情况。

1.const 修饰 *p,指向的对象只读,指针的指向可变:

int a = 10;
int b = 12;
const int *p = &a;//p是一个指向int类型的const值,与int const *p等价
*p = 11;    //编译错误,指向的对象是只读的,不可通过p进行改变
p = &b;     //合法,改变了p的指向

const int* p; 这是修饰了谁呢?

其实我们可以这样想,如果我们把int 拿出来 也就是 const int (*p); 等价于 int const (*p);

由此我们可以看出来const修饰了p啊! 也就是指向的内容不可以改变,比如p已经指向a变量,但是p=11;会报错,因为*p不可改变 但是地址是可以改变的。

比如b=12, p=&b;是正确的,因为改变了p的指向。

2.const修饰p,指向的对象可变,指针的指向不可变:

int a = 10;
int b = 12;
int * const p = &a;//p是一个const指针
*p = 11;    //合法,
p = &b;     //编译错误,p是一个const指针,只读,不可变

3.指针不可改变指向,指向的内容也不可变:

int a = 10;
int b = 12;
const int * const p = &a;//p既是一个const指针,同时也指向了int类型的const值
*p = 11;    //编译错误,指向的对象是只读的,不可通过p进行改变
p = &b;     //编译错误,p是一个const指针,只读,不可变

看完上面几种情况之后是否会觉得混乱,并且难以记忆呢?我们使用一句话总结:

const放在的左侧任意位置,限定了该指针指向的对象是只读的;const放在的右侧,限定了指针本身是只读的,即不可变的。

如果还不能很好的理解,可以去掉类型说明符,例如:

const *p; //修饰*p,指针指向的对象不可变
* const p; //修饰p,指针不可变
const * const p; //第一个修饰了*p,第二个修饰了p,两者都不可变

库函数中const怎么用呢!

实际上,为我们可以经常发现const关键字的身影,例如很多库函数的声明:

#include <string.h>
int strncmp(const char *s1, const char *s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);
har *strncpy(char *restrict s1, const char *restrict s2, size_t n);

通过看strncmp函数的原型可以知道,源字符串s2是只读的,不可变的,而s1并没有该限制。

修饰全局变量

全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改。例如:

test1.c
定义一些全局变量。

const doubule PI = 3.141;

test2.c
使用在其他文件中定义的全局变量。

extern const double PI;

其次是将常量放在一个include文件中。这时还必须使用静态外部存储类:

constant.h
定义一些全局变量。

static const double PI = 3.141;
/*test1.c——使用在其他文件中定义的全局变量*/

#include "constant.h"

/*test2.c——使用在其他文件中定义的全局变量*/

#include "constant.h"

如果不使用关键字static,在文件test1.c和test2.c中包含constant.h将导致每个文件都有统一标示符的定义声明。导致编译会出现重复定义的错误。

修饰函数的返回值

如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。

const char * GetString();

如下语句将出现编译错误:

char *str = GetString();

正确的用法是:

const char *str = GetString();

总结

借助上面理解,就会发现以下几种等价情况:

const int NUM = 11; //与int const NUM等价
int a = 12;
const int *p = &a;//与int const *p等价
const int arr[] = {0,7,2,3,4}; //与int const arr[]等价

const 的好处是引入了常量的概念,让我们不要去修改不该修改的内存。直接的作用就是让更多的逻辑错误在编译期被发现。

在这里插入图片描述

欢迎关注公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。进入技术交流群。网盘资料有如下:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值