const用法详解

本文详细解析了const修饰的变量与普通变量的区别,包括在C和C++中的差异,以及const与一级、二级指针的结合使用。重点讨论了const变量的不可变性、类型转换公式,并通过例题探讨了const与指针、引用的结合应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const修饰的变量和普通变量的区别

基本理解:

  • 普通的变量可以作为左值。
  • const修饰的变量不能再作为左值。(值初始化完成后,不能被修改)
#include<stdio.h>

int main()
{
	int a = 10;
	a = 20;//ok

	const int b = 20;
	b = 30;//err
	return 0;
}

C和C++中const的区别

相同点都不能再作为左值出现

不同点:

  • const编译方式不同

  • C中,const就是当作一个变量来编译生成指令

  • C++中,所有出现const常量名字的地方,都被常量的初始值替换了。

  • 初始化方式

  • C中,const修饰的量未进行初始化可以编译通过(但是如果不进行初始化,就失去了给它合法值的机会) 常变量

  • C++中,const修饰的量必须进行初始化,否则编译出错。 常量

注意:
我们说const修饰的量不能再作为左值,但是const修饰的量,这个量的内存能不能被修改呢??

内存是可以修改的,可以通过汇编指令或者指针进行修改。
const只是在语法上保证它修饰的量不能被作为左值进行修改。其内存是可以修改的。

以下代码就是通过指针对a所在的内存中的值进行了修改。

#include<stdio.h>

int main()
{
	const int a=10;
	int *p = (int *)&a;
	*p = 40;

	printf("a=%d,*p=%d,*(&a)=%d", a, *p, *(&a));
	return 0;

}
#include<stdio.h>
int main()
{
	const int a = 20;
	int array[20] = {};

	int *p = (int *)&a;
	*p = 30;

	printf("a=%d,*p=%d,*(&a)=%d", a, *p, *(&a));
	return 0;

}

const修饰的量应注意的

  • 常量不能再作为左值
  • 不能把常量的地址泄露给一个普通的指针或普通的引用变量

C++的语言规范:const修饰的是离它最近的类型

当const右边没有指针(*)时,const是不参与类型的

—————————————————————————————————————

const和一级指针的结合

const和一级指针的结合方式

int *q1=nullptr;
int *const q2=nullptr;

cout<<typeid(q1).name()<<endl;   //int *
cout<<typeid(q2).name()<<endl;   //int *
 const int *p;
/*
* const修饰的类型是int  
* 修饰的表达式是*p,*p不能再被赋值
* 可以任意指向不同的int类型的内存
* 但是不能通过指针间接修改指向内存的值
*/


int const *p;
/*
*  const修饰的类型是int 
*  const修饰的表达式是*p
*/



int *const p;
/*
* const修饰的类型是int *
* const修饰的表达式是 p
* p不能再被修改,p是常量,不能再指向其他内存
* (*p)可以被赋值,可以通过指针解引用修改指向内存的值
*/


const int *const *p
/*
* (*p)不能被赋值
* p不能被赋值
* p不能再指向其他内存
* 不能通过p解引用修改p所指向内存的值
*/

const和一级指针的类型转换公式

int  *      <=   const int *  //error
const int * <=    int  *      //ok


int *const  <=    int *       //ok
int *       <=    int *const  //ok


面试题

int a=10;
const int *p=&a;
int *q=p; //error  int * <=const int *
cout<<typeid(p).name()<<endl;// int const *  ,const在int的左右无所谓
/*
* 问题?
* p中放的是整型常量的地址,不能把整型常量的地址赋值给一个普通指针
*/

const和二级指针的结合

int a=10;
int *p=&a;
const int **q=&p;//const int **  <= int **

const和二级指针的结合方式

const int **q;
/*
* const修饰的类型是int
* const修饰的表达式是**q
* (**q)不能被修改
* q可以被修改
* (*q)可以被修改
*/




int *const *q;
/*
* const修饰的类型是int *
* const修饰的表达式是*q
* (*q)不能被赋值
* (**q)可以被赋值
* q可以被赋值
*/



int **const q
/*
* const修饰的类型是int **
* const修饰的表达式是q
* q不能被赋值
* (*q)可以被赋值
* (**q)可以被赋值
*/

const和二级指针的类型转换公式

  • 要么两边都必须有const
  • 要么两边都没有const
int ** <= const int **   //error
const int ** <= int **  //error


int ** <=int *const *
 /*
 * 属于const和一级指针的结合
 * 两边都去掉int*
 * 变为( * <= const *  ) error
 */

int *const * <= int **
/*
* 还是相当于const和一级指针的结合
* 两边都去掉int *
* const *  <=  *   ok
*/

转换错误原因分析

如果const int ** <= int ** 能够成立的话,就有可能把一个常量的地址泄露给一个普通指针,这是不允许的。
在这里插入图片描述

解决办法:

  • 让const 修饰*p (const int *p), *p不能被赋值,这样就不可能通过p解引用把常量的值修改了。
  • 让const修饰*q (const int *const *q), *q不能被赋值,就不可能通过 *q=&b这样的方式把一个常量的地址泄漏给一个普通指针

const和一级指针、二级指针结合的典型例题

int a = 10;
const int *p = &a;//const int * <= int *    ok
int *q = p;  //  int *  <= const int *    error
int a = 10;
int *const p = &a;//int *  <=  int *
int *q = p;//int * <= int *
int a = 10;
int *const p = &a; //int *  <=  int *   
int *const q = p; //int *  <=  int *
int a = 10;
int *const p = &a;//int *  <=  int *   ok
const int *q = p;//const int *  <= int *   ok
int a = 10;
int *p = &a; //int * <=  int *
const int **q=&p;//const int ** <=  int **   error
int a = 10;
int *p = &a;//int * <= int *
int *const*q = &p;   ok
/*
* int * const * <= int **   
* const 跟一级指针的结合
* const *  <=  *   ok
*/
int a = 10;
int *p = &a;//int *  <= int *
int **const q = &p;//int ** <= int **   ok
int a = 10;
int *const p = &a;//int *  <= int *
int **q = &p; //error
/*
* int ** <= int *const *
* const 跟一级指针的结合
* * <= const *   error
*/
int a = 10;
const int *p = &a;//const int *    <=  int *    ok
int *const* q = &p;//int *const *  <=  const int **
/*
* 首先看左边的const,const跟一级指针结合多了一个const   ok
* 再看右边的const,转换成int *  <=  const int *    error
*/

const与一级指针、引用结合的典型例题

int a=10;
int *const p=&a;//p为常量
int *&q=p;//error
//int *&q=p  <==>  int **q=&p

/*
* 错误原因在于把常量p的地址泄漏给了一个普通的二级指针
* 
*/
int a=10;
const int *p=&a;
int *&q=p;//error

/*
* int *&q=p  <==>  int **q=&p
* int ** <=> const int 
*/
int a=10;
int *p=&a;
const int *&q=p;//error

/*
* const int *&q=p <==> const int **q=&p
* const int ** <==>  int **  error
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值