C语言进阶——一文带你深度了解“C语言关键字”(中篇6)
本篇文章记录我学习C语言进阶知识——C语言关键字,旨在记录分享,希望我的分享能带给你不一样的收获!
目录
一、return关键字
二、const 关键字也许该被替换为 readolny
(一)、 const 修饰的只读变量
(二)、 节省空间,避免不必要的内存分配,同时提高效率
(三)、修饰一般变量
(四)、修饰数组
(五)、修饰指针
(六)、修饰函数参数
(七)、修饰函数的返回值
三、结语
一、return关键字
刚开始学习C语言的时候,大家因该知道return关键字最重要的作用就是:终止一个函数并返回其后面跟着的值。
return (Val); //此括号可以省略。但一般不省略,尤其在返回一个表达式的值时。
return 可以返回些什么东西呢?看下面例子:
char * Func(void)
{
char str[30];
…
return str;
}
str 属于局部变量,位于栈内存中,在 Func 结束的时候被释放,所以返回 str 将导致错误。
既然如此,那我们就深度来探讨一下C语言return 关键字的一些使用规则。
【规则1】return语句不可以返回指向“栈内存”的“指针”,因为该内存在函数体结束时会被自动销毁。
这里大家再来探讨一个问题:
return ;
这个语句有问题吗?如果没有问题,那返回的是什么?
void
函数中的return;
:如果函数的返回类型是
void
,那么return;
用于结束函数的执行。例子:
void myFunction()
{
……// 执行一些操作
return; // 结束函数,不返回任何值
}
- 非
void
函数中的return;
:对于返回类型不是
void
的函数(如int
、float
等),使用return;
是不合法的,因为这些函数需要返回一个值。如果试图在这样的函数中使用
return;
,编译器会报错。int myFunction()
{
…… // 执行一些操作
return; // 错误,缺少返回值
}
二、const 关键字也许该被替换为 readolny
const 是 constant 的缩写,是恒定不变的意思,也翻译为常量、常数等。很不幸,正是因为这一点,很多人都认为被 const 修饰的值是常量。这是不精确的,精确的说应该是只读的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。或许当初这个关键字应该被替换为 readonly。那么这个关键字有什么用处和意义呢?
const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
我们看看它与 define 宏的区别。 (很多人误以为 define 是关键字,在这里我提醒你再回到本章前面看看 32 个关键字里是否有 define)。
(一)、 const 修饰的只读变量
定义 const 只读变量,具有不可变性。
例如:
const int Max=100;
int Array[Max];
这里请在 Visual C++6.0 里分别创建.c 文件和.cpp 文件测试一下。你会发现在.c 文件中,编译器会提示出错,而在.cpp 文件中则顺利运行。为什么呢?我们知道定义一个数组必须指定其元素的个数。这也从侧面证实在 C 语言中, const 修饰的 Max 仍然是变量,只不过是只读属性罢了;而在 C++里,扩展了 const 的含义,这里就不讨论了。
注意: const 修饰的只读变量必须在定义的同时初始化,想想为什么?
留一个问题: case 语句后面是否可以是 const 修饰的只读变量呢?请动手测试一下。
【答案】
const
修饰的只读变量必须在定义时初始化,因为它的值在初始化之后不能被修改。这样做有几个原因:
确保值不变:
const
变量在定义时必须初始化,这样编译器能够知道其初始值,并确保在整个程序的生命周期中不会被修改。如果没有初始值,编译器无法保证变量的不可变性。内存管理:在编译时,
const
变量的值可以被直接嵌入到代码中或放置在只读存储区。如果没有初始化,编译器无法为其分配适当的存储位置或内存,导致无法确保变量值的不可变性。程序正确性:在程序运行时,
const
变量的不可变性是通过初始化保证的。如果没有初始化,可能会出现未定义行为或程序错误,因为变量的值可能未被设定或被错误地修改。
在 C 和 C++ 中,
case
语句后面通常需要是编译时常量(即常量表达式),而const
修饰的只读变量可以用作case
标签,但有一些细节需要注意:1. 编译时常量要求
- 在
switch
语句的case
标签中,必须使用编译时常量。编译时常量是指在编译时已知的常量值。这意味着case
标签的值必须在编译时确定。2.
const
变量的使用
const
修饰的变量的值在程序运行时是不可修改的,但是编译器在编译阶段需要知道其具体值。只要const
变量是在编译时能够确定其值的常量,编译器就可以接受它作为case
标签。const int VALUE = 5;
switch (x) {
case VALUE:
// 执行相关代码
break;
// 其他 case 标签
}
在这种情况下,如果VALUE
在编译时是一个已知的常量值(例如常量表达式),那么它是可以作为case
标签的。需要注意的点
const
变量初始化:const
变量必须在定义时初始化,并且初始化值必须是编译时常量。编译器支持:某些编译器可能会对
const
变量的支持有所不同,但在标准的 C 和 C++ 中,const
变量在符合编译时常量的条件下通常是可以用于case
标签的。避免未定义行为:确保
const
变量在编译时能够确定其值,避免使用运行时值或非编译时常量,否则会导致编译错误或未定义行为。
(二)、 节省空间,避免不必要的内存分配,同时提高效率
编译器通常不为普通 const 只读变量分配存储空间,而是将它们保存在符号表中,这使
得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。
例如:
#define M 3
const int N=5;
......
int i=N;
int I=M;
int j=N;
int J=M;//宏常量
//此时并未将 N 放入内存中//此时为 N 分配内存,以后不再分配!
//预编译期间进行宏替换,分配内存
//没有内存分配
//再进行宏替换,又一次分配内存!const 定义的只读变量从汇编的角度来看, 只是给出了对应的内存地址, 而不是像#define
一样给出的是立即数,所以, const 定义的只读变量在程序运行过程中只有一份拷贝(因为
它是全局的只读变量,存放在静态区),而#define 定义的宏常量在内存中有若干个拷贝。
#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。
#define 宏没有类型,而 const 修饰的只读变量具有特定的类型。
(三)、修饰一般变量
一般常量是指简单类型的只读变量。这种只读变量在定义时,修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。例如:
int const i=2; 或 const int i=2;
(四)、修饰数组
定义或说明一个只读数组可采用如下格式:
int const a[5]={1, 2, 3, 4, 5};或
const int a[5]={1, 2, 3, 4, 5};
(五)、修饰指针
const int *p;
int const *p;
int *const p;const int *const p;
// p 可变, p 指向的对象不可变
// p 可变, p 指向的对象不可变
// p 不可变, p 指向的对象可变//指针 p 和 p 指向的对象都不可变
这里给出一个记忆和理解的方法:
先忽略类型名(编译器解析的时候也是忽略类型名),我们看 const 离哪个近。 “近水楼
台先得月”,离谁近就修饰谁。
const int *p;
int const *p;
int *const p;const int *const p;
//const 修饰*p,p 是指针, *p 是指针指向的对象,不可变
//const 修饰*p,p 是指针, *p 是指针指向的对象,不可变
//const 修饰 p, p 不可变, p 指向的对象可变//前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p 指向的对象都不可变
(六)、修饰函数参数
const 修饰符也可以修饰函数的参数,当不希望这个参数值被函数体内意外改变时使用。例如:
void Fun(const int i);
告诉编译器 i 在函数体中的不能改变, 从而防止了使用者的一些无意的或错误的修改。
(七)、修饰函数的返回值
const 修饰符也可以修饰函数的返回值,返回值不可被改变。例如:
const int Fun (void);
在另一连接文件中引用 const 只读变量:
extern const int i; //正确的声明
extern const int j=10; //错误!只读变量的值不能改变。
注意这里是声明不是定义,关于声明和定义的区别,请看关于关键字的第一篇文章。
讲了这么多讲完了吗?远没有。在 C++里,对 const 做了进一步的扩展,还有很多知识未能
讲完。有兴趣的话,不妨查找相关资料研究研究。
三、结语
关于本次C语言关键字的进阶知识就分享到此了,“学如逆水行舟,不进则退”,愿我们一起努力,逐梦不止,砥砺前行!
相关文章:

C语言进阶——一文带你深度了解“C语言关键字”(中篇6)
本篇文章记录我学习C语言进阶知识——C语言关键字,旨在记录分享,希望我的分享能带给你不一样的收获! 目录 一、return关键字 二、const 关键字也许该被替换为 readolny (一)、 const 修饰的只读变量 (二…...

自建极简Ethercat主站-第8章 FOE基础功能实现
文章目录 第8章 FOE8.1 FOE简介8.2 FOE 数据结构8.2.1 FOE帧格式8.2.2 FOE请求8.3 数据传输流程8.3.1 读流程8.3.2 写流程8.3.3 忙操作8.3.4 代码示例第8章 FOE 源码地址 8.1 FOE简介 FOE(File Access over Ethercat),用于节点之间的文件传输。协议类似于TFTP协议,感觉…...

SQL Zoo 8.Using Null
以下数据均来自SQL Zoo 1.List the teachers who have NULL for their department.(列出所属部门为NULL的教师) select name from teacher where dept is null 2.Note the INNER JOIN misses the teachers with no department and the departments wit…...

LeetCode274. H 指数
题目链接: 274. H 指数 - 力扣(LeetCode) 思路分析:这个题目可以使用哈希表来以空间换时间,我们设置一个数组v来统计每一个对应的影响因子的文章出现的数量,遍历一遍后,v[i]表示影响因子为i的…...

概述:Dubbo、Nacos、 Zookeeper 等分布式服务协调与治理等技术
目录 1. Dubbo 2. Nacos 3. Zookeeper Dubbo、Nacos、Zookeeper 是分布式服务协调与治理领域中的关键技术,它们在微服务架构和分布式系统中扮演着重要角色。以下是对这些技术的详细介绍: 1. Dubbo 概述: Dubbo 是一个高性能、轻量级的开…...

【LINUX】小工具降耦合,全内核函数插入宏摸索测试中。。
这阵子把这个小工具对外的耦合度降了下, include/linux/printk_self.h r77683962/linux-6.9.0 - Gitee.comhttps://gitee.com/r77683962/linux-6.9.0/blob/master/include/linux/printk_self.h 这个用于初始化打印日志的级别和打印次数: void Param…...

24/8/12算法笔记 复习_线性回归
import numpy as np#导入包 X np.array([[1,1],[2,1]])#构造矩阵 y np.array([14,10])np.linalg.solve(X,y) #linalg是线性代数,用于求解线性方程AX b,solve计算线性代数回归问题X.T#转置 a X.T.dot(X)#矩阵乘法B np.linalg.inv(a)#求逆矩阵from sklearn.linea…...

Linux系统驱动(十四)输入子系统
文章目录 一、输入子系统(一)输入子系统框架结构(二)输入子系统的API 二、实现两个按键的驱动(一)实现思路(二)代码实现 一、输入子系统 在linux系统中使用输入子系统驱动上报鼠标&…...

力扣(2024.08.12)
1. 98:验证二叉搜索树 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def isValidBST(self, r…...

最新版的AutoGPT,我搭建好了
最近AutoGPT不是更新了嘛 安装 我按照官方的教程 在本地搭建好了 改动 可见的改动,主要是把原来的纯命令行改成前后端的形式 看下前端界面 界面比较简单,主要分3个大块 监控 第一个是监控 主要是看你在 build 里构建的Agents的运行情况 build 第一个是Ag…...

[SWPUCTF 2021 新生赛]PseudoProtocols(构造伪协议)
打开题目所给的环境我们可以看到这样一句话: 这里我先尝试访问/hint.php ,但是发现什么都没有发生, F12查看源代码也并没有发现什么,到这里来看的话似乎没有思路了,但是这个题的题目已经给了我们很明显的提示ÿ…...

基于STM32开发的智能语音助手系统
目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 智能家居控制个人语音助理常见问题及解决方案 常见问题解决方案结论 1. 引言 随着人工智能技术的发展,智能语音助手已经逐渐进入了人们的日常生活。…...

基于python的图像去雾算法研究系统设计与实现
博主介绍: 大家好,本人精通Java、Python、C#、C、C编程语言,同时也熟练掌握微信小程序、Php和Android等技术,能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验,能够为学生提供各类…...

自定义 View 可以播放一段视频
请实现一个自定义 View 的核心代码,核心要求可以响应如下事件: // - 要求自定义 View 可以播放一段视频 / - 在 view 左侧区域上下滑动,可以提高减少音量 / / - 在 view 右侧区域上下滑动可以提高减少屏幕亮度 // - 在 view 左右滑动可以…...

LVS负载均衡集群部署之—NAT模式的介绍及搭建步骤
一、环境准备 1.准备三台rhel9服务器 服务器名称 主机名 ip地址备注LVS调度服务器lvs.timinglee.org eth0:172.25.254.100(外网) eth1:192.168.0.100(内网) 关闭selinux和防火墙webserver2网站服务器webserver1.timinglee.orgeth0:192.168.…...

【算法】浅析哈希算法【附代码示例】
哈希算法:数据存储与检索的基石 1. 引言 在计算机科学中,哈希算法是一种用于将数据(如文件、网络地址或数据库记录)转换为固定长度的哈希值的过程。哈希值通常是一个较短的数字或字符串,用于快速检索原始数据或验证数…...

2024.8.12
2024.8.12 【梦最让我费解的地方在于,明明你看不清梦里人们的脸,却清晰地知道他们是谁。】 Monday 七月初九 序理论 最小链覆盖&最长反链长度 我们设定一个二元关系符R和一个集合A 我们设定<A,R>这样一个类群,那么对于任意 a i…...

使用Python解析pdf、docx等格式文件。
针对不同类型的文件,需要采取特定的访问与解析策略来有效获取其中蕴含的知识。下面我们将介绍对于不同数据源数据的获取方式。 1 解析Docx文档 1.1 获取Docx文档中文本 from docx import Document # pip install python-docx # python-docx 0.8.11 filename xx…...

Linux网络通信基础API
这篇文章只有Linux网络通信基础API大参数信息,和返回值,这篇文章并没有这些基础API的参数类型介绍。accept的第二个参数可以查看客户端信息。 创建socket #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int sock…...

Python爬虫:下载4K壁纸
🎁🎁创作不易,关注作者不迷路🎀🎀 目录 🌸完整代码 🌸分析 🎁基本思路 🎁需要的库 🎁提取图片的链接和标题 👓寻找Cookie和User-Agent &…...

2024年【北京市安全员-B证】新版试题及北京市安全员-B证免费试题
题库来源:安全生产模拟考试一点通公众号小程序 2024年【北京市安全员-B证】新版试题及北京市安全员-B证免费试题,包含北京市安全员-B证新版试题答案和解析及北京市安全员-B证免费试题练习。安全生产模拟考试一点通结合国家北京市安全员-B证考试最新大纲…...

python爬取B站视频实验
实验17:爬虫2 文章目录 实验17:爬虫21.实验目标及要求2. 实验主要内容3.实验小结 1.实验目标及要求 (1)掌握有关爬虫的包 (2)掌握爬虫方法 (3)爬取B站卡塔尔世界杯若干视频 2. 实验…...

10步搞定Python爬虫从零到精通!
学习Python网络爬虫可以分为以下几个步骤,每一步都包括必要的细节和示例代码,以帮助你从零开始掌握这一技能。 第一步:理解网络爬虫基础 什么是网络爬虫? 网络爬虫是一种自动化程序,用来从互联网上收集数据.它通过发送 HTTP 请求…...

SpringMVC学习笔记---带你快速入门和复习
一、初识SpringMVC 1.1、什么是SpringMVC 1.1.1、什么是MVC MVC是一种软件架构模式(是一种软件架构设计思想,不止Java开发中用到,其它语言也需要用到),它将应用分为三块: M:Model࿰…...

Linux系统编程 day09 线程同步
Linux系统编程 day09 线程同步 1.互斥锁2.死锁3.读写锁4.条件变量(生产者消费者模型)5.信号量 1.互斥锁 互斥锁是一种同步机制,用于控制多个线程对共享资源的访问,确保在同一时间只有一个线程可以访问特定的资源或执行特定的操作…...

Vue快速入门(四)——Vue3及组合式API(一)
文章目录 一、认识Vue31. Vue2 选项式 API vs Vue3 组合式API2. Vue3的优势二、使用create-vue搭建Vue3项目1、认识create-vue2. 使用create-vue创建项目三、组合式API - setup选项1. setup选项的写法和执行时机2. setup中写代码的特点3. `<script setup>`语法糖4.小结四…...

vue项目名修改、webstorm和idea创建的项目重命名、重构项目、修改项目名称
一、需求 就是创建了一个项目,后期需要重命名,怎么办?----> 直接修改?肯定不行,因为里面有些配置也需要修改,假如你只改文件夹名称的话,里面配置都没修改,后期可能会出问题。 二…...

【MySQL】数据库约束和多表查询
目录 1.前言 2.数据库约束 2.1约束类型 2.2 NULL约束 2.3 NUIQUE:唯一约束 2.4 DEFAULT:默认值约束 2.5 PRIMARY KEY:主键约束 2.6 FOREIGN KEY:外键约束 1.7 CHECK约束 3.表的设计 3.1一对一 3.2一对多 3.3多对多 …...

抖店飞鸽客服自动回复软件开发教程与下载体验(.NET版)
转载请注明出处! 原文链接:https://blog.csdn.net/zgyulongfei/article/details/140960430 本文适合的读者为: 抖店(抖音小店)个体商家;抖店店群商家(店群商家:指的是开了几十个抖…...

如何关闭redis的自动清理缓存,声明式事务(含有redis)如何解决,redis setnx锁的使用。
20240809 一、解决redis数据被删除的方案1、发现问题2、解决注意!! 二、声明式事务(当有redis的时候)1. 先看代码2. Transactional(rollbackFor Exception.class)3. 如何解决redis在事务里面,如何保证原子性和一致性3…...