C语言const关键字的用法详解

 更新时间:2022年08月18日 11:08:30   作者:Love coldplay  
今天探讨const,首先来说是将变量常量化。为什么要将变量常量化,原因有诸多好处有诸多。比如可以使数据更加安全不会被修改

1 介绍

const关键字是constant的缩写,翻译为常量、常数。在C语言中const的作用很强大,它可以修饰变量、数组、指针、函数参数等。

1.1 const修饰变量

const修饰变量,表示希望此变量具有只读性,防止被直接直接修改。

//const关键字是constant的缩写,翻译为常量、常数。
//在C语言中const的作用很强大,它可以修饰变量、数组、指针、函数参数等。
#include<stdio.h>
int main()
{
	const int num = 100;
	num = 20;
	printf("%d\n", num);
}

发现const 修饰的变量,随后试图修改num的值,结果出现红色波浪线,编译器提醒我们:表达式必须是可修改的左值。

所以我们得出结论:const修饰的变量,不能被修改。

const修饰的变量就一定不能被修改吗???

	const int num = 100;
	int *p = &num;
	*p= 20;
	printf("%d\n", num);

运行结果

通过上图我们发现num的值被修改了,通过指针可以间接的修改const修饰的变量。

但是运行时会出现警告:warning C4090: “初始化”: 不同的“const”限定符。

是因为num类型是const修饰,但是p是整型指针变量 ,

类型不同。所以通过下面强转就没警告了。

改进后的代码

    const int num = 100;
	int *p = (int*)&num;
	*p= 20;
	printf("%d\n", num);

总结:const修饰的变量不能被直接修改

1.2 const修饰数组

#include<stdio.h>
int main()
{
	const int array[5] = { 0,1,2,3,4 };
	array[0] = 100;
}

表示const修饰的数组也不能被修改。

通过上面1.1const修饰变量的分析,同理也联想到:指针是否可以修改数组的内容。结果如下:

#include<stdio.h>
int main()
{
	const int array[5] = { 0,1,2,3,4 };
	//array[0] = 100;
	int *p = array;
	*p = 100;
	printf("%d\n", array[0]);
}

不难发现,指针可以修改。和1.1节出现结果一样,同样运行时程序出现了警告:warning C4090: “初始化”: 不同的“const”限定符,同样的警告出现了。

经过强转后:

#include<stdio.h>
int main()
{
	const int array[5] = { 0,1,2,3,4 };
	//array[0] = 100;
	int *p = (int *)array;//array原本的数据类型为const int[5]
	*p = 100;
	printf("%d\n", array[0]);
}

总结:const修饰数组时,其值不能被直接修改

1.3 const修饰指针

此部分分为两种情况去分析:

#include<stdio.h>
int main()
{
	int a = 100;
	const int *p = &a;
	*p = 1000;
	printf("%d\n", a);
}

此时,通过上图容易发现const修饰指针指向的内容一旦修改,就会自动报错,所以*p(指针指向的内容不能被修改),但指针变量p本身是可以被修改的。

#include<stdio.h>
int main()
{
	int a = 100;
	int* const p = &a;//p的数据类型为int *const
	*p = 1000;
	printf("%d\n", a);
}

此时,const修饰的是指针p本身,所以指针本身不能被修改,但是指针所指向的内容*p可被修改

1.4 const修饰函数参数

#include<stdio.h>
int myFunc(const int* p)
{
	*p = *p + 1;
	return *p;
}

const修饰函数参数,对参数起到限定的作用, 通过发现指针也能修改其值。

总结:const修饰函数参数,本质上和修饰变量和指针一样。表示其值不能被直接修改。

2 const对程序的影响

可以发现,在*p下面出现了红色波浪线,让上述的错误提前出现,避免程序在运行时出错。

总结:编译器可以对const修饰的变量进行合理性检查,让错误提前出现。

3 总结

通过这篇博客,我对const修饰变量、数组、指着和函数参数进行了归纳总结。总体来说有几个点需要注意:

const修饰变量,不能被直接修改
const修饰指针指向的内容时(const int * p=&a),指针指向内容(*p)不能被修改,但指针本身(p)可以被修改。
const修饰指针本身时(int * const p =&a),指针指向的内容(*p)可以被修改,但是指针本身(p)不能被修改。
const 修饰字符串 (const *p=“abcd”;)和(const p[]=“abcd”;)这两种情况的分析,前者字符串不能修改,后者字符串可以修改。这    是由C语言使用存储器的方式决定的。

补充内容

char *cards = “JQK”; 的情况下计算机操作的步骤:

计算机做的步骤:

计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。

程序在栈上创建cards变量
栈是存储器中计算机用来保存局部变量的部分,局部变量也就是位于函数内部的变量,cards变量就在这个地方。

cards变量设为"JQK"的地址
cards变量将会保存字符串字面值"JQK"的地址。为了防止修改,字符串字面值通常保存在只读存储器中。

计算机试图修改字符串
程序试图修改cards变量指向的字符串中的内容时就会失败,因为字符串是只读的。

char cards[] = “JQK”;的情况下计算机操作的步骤:

计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。

程序在栈上新建了一个数组
我们声明了数组,所以程序会创建一个足够大的数组来保存字符串"JQK"

程序初始化数组
除了为数组分配空间,程序还会把字符串字面值"JQK"的内容复制到栈上。

补充内容

char *cards = “JQK”; 的情况下计算机操作的步骤:

计算机做的步骤:

计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。

程序在栈上创建cards变量
栈是存储器中计算机用来保存局部变量的部分,局部变量也就是位于函数内部的变量,cards变量就在这个地方。

cards变量设为"JQK"的地址
cards变量将会保存字符串字面值"JQK"的地址。为了防止修改,字符串字面值通常保存在只读存储器中。

计算机试图修改字符串
程序试图修改cards变量指向的字符串中的内容时就会失败,因为字符串是只读的。

char cards[] = “JQK”;的情况下计算机操作的步骤:

计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。

程序在栈上新建了一个数组
我们声明了数组,所以程序会创建一个足够大的数组来保存字符串"JQK"

程序初始化数组
除了为数组分配空间,程序还会把字符串字面值"JQK"的内容复制到栈上。

区别:

原来的代码使用了指向只读字符串字面值的指针;而在第二段代码中,用字符串字面值初始化了一个数组,从而得到了这些字母的副本,这样就可以随意修改他们了。

到此这篇关于C语言const关键字的用法详解的文章就介绍到这了,更多相关C语言const内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 用C++类实现单向链表的增删查和反转操作方法

    用C++类实现单向链表的增删查和反转操作方法

    下面小编就为大家带来一篇用C++类实现单向链表的增删查和反转操作方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 基于c++的中国象棋游戏设计与实现

    基于c++的中国象棋游戏设计与实现

    这篇文章主要介绍了基于c++的中国象棋游戏设计与实现,主要操作是possibleMove(int x, int y),通过整个棋盘每个位置上的信息、中国象棋的规则来获得位置(x, y)这个棋子可以移动到的位置,需要的朋友可以参考一下
    2022-02-02
  • c语言socket多线程编程限制客户端连接数

    c语言socket多线程编程限制客户端连接数

    这篇文章主要介绍了c语言socket多线程编程,可以限制客户端连接数,大家参考使用吧
    2013-12-12
  • C语言中continue的用法详解

    C语言中continue的用法详解

    在C语言当中的continue和break语句是有一些类似的,但是它并不是强制进行终止的,下面这篇文章主要给大家介绍了关于C语言中continue用法的相关资料,需要的朋友可以参考下
    2022-11-11
  • C++计算圆形、矩形和三角形的面积

    C++计算圆形、矩形和三角形的面积

    这篇文章介绍了C++计算圆形、矩形和三角形面积的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • C++中指针函数与函数指针的使用

    C++中指针函数与函数指针的使用

    今天小编就为大家分享一篇关于C++中指针函数与函数指针的使用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • C++构造函数一些常见的坑

    C++构造函数一些常见的坑

    这篇文章主要给大家分享的是C++构造函数一些常见的坑,文章围绕C++构造函数的相关资料展开关于C++构造函数坑的内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-01-01
  • C语言二叉树与堆的概念与实现

    C语言二叉树与堆的概念与实现

    这篇文章主要给大家介绍了关于C语言二叉树与堆的相关资料,文章详细记录了他们的相关概念以及如何实现的,通过图文介绍的非常详细,需要的朋友可以参考下
    2021-06-06
  • 手把手带你学习C++的运算符

    手把手带你学习C++的运算符

    这篇文章主要为大家介绍了C++运算符,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助,希望能够给你带来帮助
    2021-11-11
  • 一文详解Qt如何优雅的进行界面布局

    一文详解Qt如何优雅的进行界面布局

    使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的,这种设定⽅式其实并不⽅便,尤其是界⾯如果内容⽐较多, 不好计算,所以Qt 引⼊ 布局管理器 (Layout) 机制, 来解决上述问题,需要的朋友可以参考下
    2024-05-05

最新评论