『C语言进阶』const详解

news2024/11/20 14:34:10

在这里插入图片描述
🔥博客主页 小羊失眠啦
🔖系列专栏 C语言Linux
🌥️每日语录生活便是寻求新的知识。
❤️感谢大家点赞👍收藏⭐评论✍️


在这里插入图片描述

一、什么是const

常类型,使用类型修饰符const说明的类型,常类型的变量或者对象的值是不能被更新的。

const含义:只要一个变量前用const来修饰,就意味着该变量里的数据只能被访问,而不能被修改,也就是意味着“只读”(readonly)


二、const的优点

  1. 定义常量:

    const int n=100;
    
  2. 类型检查:

    const常量与#define宏定义常量区别:

    • const定义变量类型只有整数或者枚举,并且常量表达初始化才为常量表达式

    • 预编译指令只是对进行简单的替换,不能进行类型检查,相比之下,被const修饰的变量有自己的类型,编译器可以通过安全检查

    • 其余情况下const常量只是一个被const限定的变量,不能与常量混肴

  3. 可以保护被修饰的东西,防止意外修改,增强程序的健壮性

  4. 可以避免不必要的内存分配,编译器通常不为被const修饰的变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。


三、const的用法:

3.1 修饰全局变量

此时全局变量只能使用不可修改,直接修改(编译报错)与修改地址(程序异常)都不行

#include <stdio.h>
//const修饰全局变量
//此时全局变量只能使用不可修改,直接修改(编译报错)与修改地址(程序异常)也不行
const int a = 100;
void test()
{
    printf("a = %d\n", a);//直接使用
    //a = 200;//直接修改,编译报错,显示a是只读的
    //printf("a = %d\n", a);
    //int *p = &a;
    //*p = 300;//通过地址修改,程序异常,有些编译器可能只会显示警告,并不会报错,且程序能正常运行,但是不会显示任何结果
    //printf("a = %d\n", a);
}
 
int main()
{
	test();
	return 0;
}

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

3.2 修饰局部变量

不可直接修改变量的值(编译报错),但是可以通过地址进行修改

const int n = 5;
int const n = 5;

这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了。

#include<stdio.h>
//const修饰普通局部变量
//不可直接修改(编译报错),但是可以通过地址进行修改
void test()
{
    const int b = 100;
    printf("b = %d\n", b);
    //b = 200;//直接修改,编译报错
    //printf("b = %d\n", b);
    int *p = &b;
    *p = 300;//通过地址进行修改
    printf("b = %d\n", b);
}
int main()
{
	test();
    return 0;
}

接下来看看const用于修饰常量静态字符串,例如:

const char* str = "fdsafdsa";

如果没有const的修饰,我们可能会在后面有意无意的写str[4]=’x’类似这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。

3.3 修饰指针变量的类型(即常量指针)

const修饰指针变量的类型,可直接修改变量值,不可修改指针指向的地址里的内容(编译报错),可以修改指针的指向

常量指针是指针指向的内容是常量,可以有以下两种定义方式:

const int * n;
int const * n;

可以发现,无论是在int前还是在int后,const一直位于*之前

#include<stdio.h>
void test()
{
    int c = 100;
    const int *p = &c;
    printf("c = %d\n",c);
    c = 111;//可以直接修改变量的值
    printf("c = %d\n",c);
    //*p = 200;//不可修改指针指向的地址里的内容,编译报错
    //printf("c = %d\n",c);
    int d =300;
    p = &d;//可以修改指针的指向
    printf("*p = %d\n",*p);
}
int main()
{
	test();
    return 0;
}

3.4 修饰指针变量(即指针常量)

可以直接修改变量的值,可以修改指针指向地址的内容,但是不能修改指针的指向(编译报错)

指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:

int *const n;
#include<stdio.h>
void test()
{
    int c = 200;
    int  * const p = &c;//const修饰指针,即指针常量
    printf("*p = %d\n",*p);
    c = 300;
    printf("c = %d\n",c);//直接修改值
    printf("*p = %d\n",*p);
    *p = 400;//修改指针指向地址里的内容
    printf("*p = %d\n",*p);
    int d =500;
    //p = &d;//不能修改指针的指向,编译报错
    //printf("*p = %d\n",*p);
}
int main()
{
	test();
	return 0 ;
}

区分常量指针和指针常量的关键就在于*的位置,以*为分界线,如果const在*的左边,则为常量指针,如果const在*的右边则为指针常量。

如果我们将*读作‘指针’,将const读作‘常量’的话,内容正好符合:

int const * n;
     常量+指针-->常量指针
int *const n;
   指针+常量  -->常量指针

3.5 指向常量的常指针

是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值

const int* const p;
#include<stdio.h>
void test()
{
    int c = 200;
    const int * const p = &c;//即修饰指针变量类型又修饰指针变量
    printf("*p = %d\n",*p);
    c = 300;//可以直接修改值
    printf("c = %d\n",c);
    printf("*p = %d\n",*p);
    //*p = 400;//不能修改指针指向地址里的内容,编译报错
    //printf("*p = %d\n",*p);
    //int d =500;
    //p = &d;//不能修改指针指向,编译报错
    //printf("*p = %d\n",*p);
}
int main()
{
	test();
	return 0;
}

四、修饰函数的参数

根据常量指针与指针常量,const修饰函数的参数也是分为三种情况

  1. 防止修改指针指向的内容

    void StringCopy(char *strDestination, const char *strSource);
    

    其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图通过解引用的方式改动 strSource 的内容,编译器将指出错误。

  2. 防止修改指针指向的地址

    void swap ( int * const p1 , int * const p2 )
    

    指针p1和指针p2指向的地址都不能修改。


五、修饰函数的返回值

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

const char * GetString(void)

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

char *str = GetString();

正确的用法是

const char *str = GetString();

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1105330.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ZY Player:影视爱好者的万能播放器

如果你是一位影视爱好者&#xff0c;一定有过为寻找一款支持各种影视资源、能解析VIP权限的播放器而头疼的经历。今天&#xff0c;我要为大家介绍一款被称为万能影视资源播放器的ZY Player&#xff0c;它由网友Hiram-Wong二次开发&#xff0c;并且是开源免费的 导航 强大的影视…

马来西亚考虑对TikTok电商实施禁令:定价和数据隐私问题浮出水面

近日&#xff0c;马来西亚政府考虑跟进印尼的政策&#xff0c;对社交媒体平台TikTok的电商交易采取一系列限制措施。这一决定产生的影响不容忽视&#xff0c;不仅对TikTok自身&#xff0c;也对整个电商行业和数字经济领域产生了重大影响。 背景 这一决策的背后&#xff0c;是马…

【yolov5目标检测】使用yolov5训练自己的训练集

数据集准备 首先得准备好数据集&#xff0c;你的数据集至少包含images和labels&#xff0c;严格来说你的images应该包含训练集train、验证集val和测试集test&#xff0c;不过为了简单说明使用步骤&#xff0c;其中test可以不要&#xff0c;val和train可以用同一个&#xff0c;…

服务器数据恢复-RAID信息破坏导致服务器操作系统无法启动的数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器&#xff0c;8块硬盘组建了一组raid5磁盘阵列&#xff0c;服务器安装的是windows server操作系统&#xff0c;上层部署ORACLE数据库。 服务器故障&#xff1a; 在服务器运行过程中&#xff0c;2块硬盘报警&#xff0c;服务器操作系统…

外汇天眼:这才是外汇维权的正确打开方式,还不get?

经常有咨询外汇天眼维权服务的投资者问天眼君&#xff0c;外汇天眼是如何帮助遭遇外汇问题的受害者们维权的&#xff0c;其实这依靠的就是外汇天眼作为第三方媒体多年来在汇圈的威望&#xff0c;以及相关的大型外汇交易商提供的专属维权客服助力解决平台用户遭遇的问题。 这是什…

【OpenVINO】行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human-上篇

行人摔倒检测 — 基于 OpenVINO C# API 部署PP-Human 1. 英特尔开发套件1.1 OpenVINO1.2 AIxBoard 介绍产品定位产品参数AI推理单元 2. PaddleDetection实时行人分析工具PP-Human3. 预测模型获取与转换3.1 PP-YOLOE行人跟踪模型介绍模型下载与转换&#xff08;1&#xff09;Pad…

港科夜闻|凯洛格-香港科大行政人员工商管理硕士课程在英国《金融时报》EMBA课程百强榜蝉联全球第一,十二度获此顶级课程殊荣...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、凯洛格-香港科大行政人员工商管理硕士课程在英国《金融时报》EMBA课程百强榜蝉联全球第一&#xff0c;十二度获此顶级课程殊荣。该EMBA排名自推出以来&#xff0c;从未有其他课程能达到或接近这样创记录的佳绩。排名榜的…

Vue3最佳实践 第八章 ESLint 与 测试 ( ESLint )

ESLint ​在所有的JavaScript 项目开发中我们都会接触到 ESLint 这个词&#xff0c;ESLint 是个什么样的组件会给为项目做些什么吗&#xff1f;ESLint 是一种检查语法错误以及代码是否按照预定规则编写的工具。ESLint 可以帮助开发者发现代码中潜在的错误。在Vue项目中Eslint一…

基于R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习高级应用

查看原文>>>【案例教程】基于R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习高级应用 Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析…

MFC扩展库BCGControlBar Pro v33.6新版亮点 - 图形管理器改造升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v33.6已正式发布了&#xff0c;此版本包含了对图表组件的改进、带隐藏标签的单类功能区栏…

智慧公厕改变城市生活,厕所革命标杆应用解决方案

随着城市化进程的加快&#xff0c;公厕作为城市基础设施的重要组成部分&#xff0c;扮演着不可忽视的角色。然而&#xff0c;传统的公厕粗放型管理模式&#xff0c;已经无法满足市民日益增长的需求。为了提升公厕的管理和服务水平&#xff0c;智慧公厕应运而生。 什么是智慧公…

百万粉丝大V将前台实名制

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 这事慢慢实锤了&#xff1a;网络大V前台实名制要实施了。 根据微博洪榕爆料&#xff1a;10月底之前&#xff0c;100万粉丝的自媒体账号前台展示真实姓名; 12月份&#xff0c;50万粉的自媒体账号前…

看了这个配电柜管理,我人都傻了!

随着社会的不断发展和电力系统的不断完善&#xff0c;配电柜监控系统变得越来越关键。系统为电力分配和管理提供了关键性的支持&#xff0c;确保电能供应的稳定性和安全性。 客户案例 工业制造业 在工业制造领域&#xff0c;电力分配至关重要。某制造公司面临着高负荷和严格的生…

自动驾驶的法律和伦理问题

随着自动驾驶技术的不断发展&#xff0c;出现了一系列与法律和伦理有关的问题。这些问题涵盖了自动驾驶的法律框架、道路规则以及伦理挑战。本文将探讨这些问题&#xff0c;并分析自动驾驶所带来的法律和伦理挑战。 自动驾驶的法律框架 自动驾驶的法律框架是制定和管理自动驾…

前端HTML要了解的知识,DOCTYPE 声明究竟是做什么的、作用是什么?

&#x1f31f;&#x1f31f;&#x1f31f; 专栏详解 &#x1f389; &#x1f389; &#x1f389; 欢迎来到前端开发之旅专栏&#xff01; 不管你是完全小白&#xff0c;还是有一点经验的开发者&#xff0c;在这里你会了解到最简单易懂的语言&#xff0c;与你分享有关前端技术和…

【Vue3】响应式原理

【Vue3】响应式原理 一、问题什么是数据响应式&#xff1f;vue2使用Object.defineProperty实现响应式&#xff1f;Proxy和Reflect1、Proxy2、Reflect3、Proxy和Reflect的使用4、 使用Proxy和Reflect完成响应式 一、问题 1、Vue3的响应式原理和Vue2有什么不同呢&#xff1f; V…

zabbix中文乱码解决方法

1、 问题描述 zabbix在页面中将语言设置为中文后出现乱码问题 监控中文乱码解决方法 1、之前看过一个从Windows里面将本机电脑字体的ttf文件传入服务器中&#xff0c;但是Windows的C&#xff1a;\windows\fonts里面的字体TTF文件可能因为权限的原因无法传到服务器上&#x…

陪诊小程序|陪诊小程序关爱健康,无忧陪伴

随着社会发展和人们生活水平的提高&#xff0c;健康问题成为人们关注的焦点。然而&#xff0c;在就医过程中&#xff0c;许多患者常常感到孤独和无助&#xff0c;缺乏得到家人陪伴的温暖与安慰。为了解决这一问题&#xff0c;我们公司开发了一款创新的陪诊小程序软件&#xff0…

开启机器人学新时代,《机器人学建模、规划与控制》完美诠释未来

机器人学是未来发展的热点领域之一&#xff0c;而在这个领域中&#xff0c;建模、规划与控制则是必不可少的基础技术。今天作者要向大家推荐一本机器人学领域的经典教材——《机器人学建模、规划与控制》。 这本书由西安交通大学出版社出版&#xff0c;作者是机器人学专业的鼎…

JSX的本质

一、本质 React.createElement即h函数&#xff0c;返回vnode第一个参数&#xff0c;可能是组件&#xff0c;也可能是html tag组件名&#xff0c;首字母必须大写&#xff08;React规定&#xff09; 二、babel试一试 &#xff08;babel集成了jsx的编译环境&#xff09; // JSX…