【重生之我要苦学C语言】深入理解指针2

深入理解指针2

const修饰指针

当const修饰变量时,是无法更该该变量的值的

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int a = 10;//const常属性,不能改变的属性a = 1;printf("%d\n", a);return 0;
}

报错:
在这里插入图片描述
a变成了常变量,a的本质还是变量,但是因为被comst修饰,所以不能改变

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int n = 10;int arr[n];return 0;
}

报错:
在这里插入图片描述
n是变量,语法限制了n只是不能被修改

在c++中,const int n里的n就是常量

如果想改变用const修饰的变量的值:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int a = 10;int* p = &a;*p = 1;printf("%d", a);return 0;
}

但这是违反规则的,因为用const修饰的a是不期望被改变的

此时,如果改为:

 const int* p = &a;

则仍无法进行变量值的修改

const修饰指针变量

有两种形式:

 const int* p = &a;

此时const限制的是*p(指针指向的内容不能改变,但指针变量本身可以改变)

int* const p = &a;

此时const限制的是*p(指针变量本身不能被修改,但指针指向的内容可以通过指针变量改变)

野指针

野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

成因:

指针未初始化:
 int* p;//局部变量不初始化的时候,里面放的是随机值*p = 20;//非法访问,p就是野指针
指针越界访问·
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0;i <= sz;i++) {*p = i;p++;}return 0;
}

当循环到第十一次的时候,p指向了数组最后一个元素后面的空间

指针指向的空间释放
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int* test() {int n = 100;return &n;
}
int main()
{int* p = test();printf("%d", *p);return 0;
}

n所占的四个字节的空间,当函数test返回之后,n的空间就还给了操作系统

如何避免野指针

指针初始化

  • 如果指针变量有明确的指向,直接就给明确的地址:
 int a = 10;int* p = &a;
  • 如果指针变量当前还不知道应该指向哪里,只是应该初始化为NULL`
int* p = NULL;

NULL是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错

小心指针越界

指针变量不使用时,及时置NULL,指针使用之前检查其有效性

if (p != NULL)

避免返回局部变量的地址

assert断言

assert.h 头文件定义了宏 assert(),用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行。这个宏常常被称为“断言”

 assert(p != NULL);

上面代码在程序运行到这一行语句时,验证变量p是否等于NULL.如果确实不等于NULL,程序继续运行,否则就会终止运行,并且给出报错信息提示:
在这里插入图片描述

assert()宏接受一个表达式作为参数。如果该表达式为真(返回值非零),assert()不会产生任何作用,程序继续运行。如果该表达式为假(返回值为零),assert()就会报错,在标准错误流 stderr中写入一条错误信息,显示没有通过的表达式,以及包含这个表达式的文件名和行号。

  • 使用assert()有几个好处:
    它不仅能自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制。如果已经确认程序没有问题,不需要再做断言,就在#include <assert.h>语句的前面,定义一个宏 NDEBUG.
 #define NDEBUG #include <assert.h>

然后,重新编译程序,编译器就会禁用文件中所有的assert()语句。如果程序又出现问题,可以移除这条#define NDEBUG 指令(或者把它注释掉),再次编译,这样就重新启用了assert()语句

  • assert()的缺点
    因为引入了额外的检查,增加了程序的运行时间

一般我们可以在Debug 中使用,在Release 版本中选择禁用assert 就行,在vs 这样的集成开发环境中,在 Release 版本中,直接就是优化掉了。这样在debug版本写有利于程序员排查问题,在Release版本不影响用户使用时程序的效率

strlen的模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str) {size_t count = 0;assert(str != NULL);while (*str) {count++;str++;}return count;
}
int main()
{char arr[] = "abcdef";size_t len = my_strlen(arr);printf("%zd", len);return 0;
}

传值调用和传址调用

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int x, int y) {int z = 0;z = x;x = y;y = z;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:%d %d\n", a, b);Swap(a, b);//传值调用printf("交换后:%d %d", a, b);return 0;
}

不能实现交换:

在这里插入图片描述
实参传递给形参的时候,形参是实参的一份临时拷贝,对形参的修改不改变实参

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int* pa, int* pb) {int z = 0;z = *pa;*pa = *pb;*pb = z;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:%d %d\n", a, b);Swap(&a,&b);//传址调用printf("交换后:%d %d", a, b);return 0;
}

传址调用可以让函数和主调函数建立起真正的联系,在函数内部可以修改主调函数的变量,所以:
函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用,如果函数内部要修改主调函数中的变量的值,采用传址调用

END……

𖠚ᐝʜɪ Nᴏ̆̈ᴠ̆̈ᴇ̆̈ᴍ̆̈ʙ̆̈ᴇ̆̈ʀ̆̈🔅
所有热爱的事情都不要留余地
十一月你好💮️

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

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

相关文章

TVM前端研究--Pass

文章目录 TVM 中 Pass 分类Pass Infrastructure后端主要数据结构前端数据结构Pass 注册机制注册流程AI 编译器一般采用多级 IR 的架构来处理深度学习模型,不同级别的 IR 包含不同层级的信息。比如,越靠近前端的 IR 一般不包含硬件的信息,越靠近后端,IR 所含信息则与硬件愈相…

半参数模型

4. 半参数模型 (Semi-parametric Model) 半参数模型结合了参数化和非参数化的方法。可以在整体上采用线性回归&#xff0c;但在局部允许非线性变化。这样做的目的是在保持模型的线性解释性的同时&#xff0c;捕捉细微的弧度趋势。 例如&#xff0c;可以定义&#xff1a; y …

终于弄懂了Python字符串的操作

字符串的操作 在 Python 中&#xff0c;字符串不仅是存储文本的工具&#xff0c;还提供了多种操作来处理和管理这些文本数据。通过掌握字符串的各种操作&#xff0c;程序员可以更加灵活地处理信息&#xff0c;实现不同的需求。以下将详细介绍字符串的常见操作&#xff0c;包括…

LInux系统编程(二)操作系统和进程

目录 一、前言&#xff1a;冯诺依曼体系结构 1、图中各个单元的介绍 2、值得注意的几点 二、操作系统 1、操作系统分层图 2、小总结 三、 进程&#xff08;重点&#xff09; 1、进程的基本概念 2、存放进程信息的数据结构——PCB&#xff08;Linux 下称作 task_struct…

加法电路和减法电路

一、加法电路 下边为加法电路的拓扑结构 加法电路作用1: 直流量叠加 如上图仿真所示,利用放大器LM324AD进行加法电路的仿真,输入为直流+1V和直流+2V,经过加法运算,根据上边Uo的计算公式进行计算,可得Uo=-3V,和仿真结果保持一致。如下图所示。 加法电路作用2: 信号叠加…

Kafka系列之:对做了条带划分的Kafka节点磁盘实现扩容的技术方案

Kafka系列之:对做了条带划分的Kafka节点磁盘实现扩容的技术方案 一、查看磁盘条带扩容情况二、查看逻辑卷及其关联的物理卷和逻辑卷快照三、显示文件系统磁盘空间使用情况及文件系统类型四、对每块盘扩容五、更改物理卷的大小六、扩展逻辑卷七、扩展XFS文件系统的大小八、扩容…

8. 数据结构——邻接表、邻接矩阵的基本操作

一、邻接表 1. 内容 2. 实现代码(直接可以复制使用) //邻接表的相关操作 #include<bits/stdc.h> #define MVnum 100 #define OK 1 #define ERROR -1 using namespace std;typedef int Status; typedef char VerTexType; //假设顶点的数据类型为char typedef int ArcT…

自动化研磨领域的革新者:半自动与自动自磨机的技术突破

据QYResearch调研团队最新报告“全球半自动和自动自磨机市场报告2023-2029”显示&#xff0c;预计2029年全球半自动和自动自磨机市场规模将达到5.3亿美元&#xff0c;未来几年年复合增长率CAGR为3.5%。 图00001. 半自动和自动自磨机&#xff0c;全球市场总体规模 如上图表/数据…

基于RFID的智能门禁系统的设计(论文+源码)

1系统总体设计 本次基于RFID的智能门禁系统的设计与实现课题&#xff0c;在功能上设计如下&#xff1a; 1.可以通过RFID模块&#xff0c;实现对IC卡的注册&#xff0c;注销操作&#xff1b; 2.在IC卡解锁时&#xff0c;如果非注册IC卡刷卡时蜂鸣器将报警提示&#xff1b; 3…

CAD图纸防泄密|哪些措施可以加密公司图纸?五个宝藏方法分享,2024必读!

在工程设计领域&#xff0c;CAD图纸作为企业的核心资产&#xff0c;其安全性至关重要。一旦图纸泄露&#xff0c;不仅可能给企业带来重大的经济损失&#xff0c;还可能损害企业的声誉和竞争力。 那么&#xff0c;怎么实现CAD图纸防泄密呢&#xff1f; 以下是五个CAD图纸防泄密…

Ubuntu:docker 安装和使用

本文将介绍在 Ubuntu 上安装和使用 docker 的方法和 bash 命令。 一、安装 sudo apt update sudo apt install docker.io二、启动 sudo systemctl start docker sudo systemctl enable docker三、下载 sudo docker pull registry.cn-hangzhou.aliyuncs.com/......四、运行 …

element-plus版本过老,自写选项弹框增删功能

title: element-plus版本过老&#xff0c;自写选项弹框增删功能 date: 2024-10-31 10:53:18 tags: element-plus 1.情景 发现代码怎么都用不了el-select的#footer插槽从而实现不了相关的操作&#xff0c;发现el-select自带的管理相关数据的属性popper-class用不了。 2.原因与…

java项目之文理医院预约挂号系统源码(springboot)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的文理医院预约挂号系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息。 项目简介&#xff1a; 本系统的使用角色可…

Ubuntu 通过Supervisor 或者 systemd 管理 .Net应用

在 Ubuntu 上安装 .NET 8.0&#xff0c;通过 supervisor 或 systemd 管理 .NET 应用服务&#xff0c;确保应用能够自动启动、运行以及在崩溃时重启。 1. 安装 .NET 8.0 最新的Ubuntu版本已经不需要注册 Microsoft 包存储库了&#xff0c;具体的可以参考微软官方文档安装&…

spring 学习路线梳理(二)注解

1.通过注解的方式创建bean 1.1 定义dao层的接口和实现 public interface ILoginDao {public String login(); }Slf4j Repository public class LoginDaoImpl implements ILoginDao {public LoginDaoImpl(){System.out.println("spring create bean call");}Override…

具有特定结构和功能的化学试剂——反式环辛烯-聚乙二醇-硅烷TCO-PEG-Silane

TCO-PEG-Silane&#xff0c;即反式环辛烯-聚乙二醇-硅烷&#xff0c;是一种具有特定结构和功能的化学试剂。 一、基本性质 外观&#xff1a;通常为白色固体&#xff0c;但具体外观可能因分子量、制备方法和存储条件的不同而有所变化。 溶解性&#xff1a;易溶于多种有机溶…

Blender进阶:着色器节点

11 着色器节点 11.1着色器 着色器Shader&#xff0c;负责给物体表面着色。 综合以下参数&#xff1a; -基础色-金属度、粗超度、透明度-法向-入射光颜色、强度、角度。。 着色器本质上是一段程序、算法&#xff0c;即着色器编程。 在节点编辑器中&#xff0c;支持算法的可…

状态检测防火墙报文处理发流程

华为大同&#xff1a;全系列状态检测防火墙报文处理流程 华为防火墙在处理报文时&#xff0c;其核心在于其状态检测与会话机制&#xff1a;当防火墙接收到报文后&#xff0c;它会在特定时间和条件下创建会话&#xff0c;并对那些与会话表匹配的报文进行特定的转发处理。基于这一…

深入探讨SEO分析技巧助力网站流量提升

内容概要 在当前的数字化时代&#xff0c;SEO分析的重要性不言而喻。它是提升网站流量的关键工具&#xff0c;帮助站长有效地优化网站内容和结构。通过系统的SEO分析&#xff0c;站长可以掌握用户搜索行为和需求&#xff0c;从而制定出更具针对性的内容策略。例如&#xff0c;…

【天线&通讯】电力设施检测系统源码&数据集全套:改进yolo11-RFCAConv

改进yolo11-DAttention等200全套创新点大全&#xff1a;电力设施检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统图片或者…