《重生到现代之从零开始的C语言生活》—— 指针2

embedded/2024/12/22 9:04:11/

const

const修饰变量

指针可以解引用修改变量,如果我们不想让它被修改可怎么办啊
这个就是const的作用

int main()
{int a = 0;a = 10;printf("%d",a)const int b = 0;b = 11;printf("%d",b);return 0;
}

在此代码中,a是可以被修改的,b是不能被修改的,因为b被const修饰从语法规则(记住是语法规则,不是把他变成了常量)上入手,给他做了限制,修改就不符合语法规则,导致没有办法直接修改变量

但是我们还是可以绕过语法规则,从地址出发改变变量

int main()
{const int a = 0;int * n = &a;*n = 10;return 0;
}

此举就是绕过语法规则,从地址上更改变量,那怎么样可以不让他从地址改变变量呢

const修饰指针

const修饰指针有三种情况

int const * a = 0;//const在*左边
int * const a = 0;//const在*右边
int const * const a  = 0;//const在*左边和右边

那么他们分别代表什么呢?

int const * a = 0;

const在*的左边,修饰的是指向的内容,就代表着指向的内容不能通过指针来改变,但是指针变量本身可以改变(可以这么理解,const的后面是解引用a,就代表了修饰的是解引用a,也就是指向变量,所以可以修改储存在指针变量里面的地址,但是不能通过解引用来修改指向的变量

int * const a = 0;

const在*的右边,修饰的是变量,就代表着指针变量本身不能修改,但是指向的内容可以被修改(const后面是a,就是修饰指针变量,所以不能修改变量本身)

如果指针变量和指向内容都不想被修改,那简单,*左右两边都写一个const不就行了(滑稽)

指针运算

指针基本运算分为三种

  • 指针加减整数
  • 指针减指针
  • 指针的关系运算

指针加减整数

指针加减整数,就是将指针的往后或往前移动整数倍的指针变量类型的字节

指针减指针

指针减指针所得的是两个指针之间的元素个数

#include<stdio.h>
int main()
{
int arr [10] = {1,2,3,4,5,6,7,8};
int * a1 = &arr[0];
int * a2 = &arr[4];
printf("%d",a1 - a2);
return 0;//运行结果为4
}

指针的关系运算

指针之间的关系也可以理解为地址和地址之间的关系
比如指针大小的比较

运用如下

#include<stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8 };int* p = &arr[0];while (p < arr + 10){printf("%d", *p);p++;}return 0;
}

野指针

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

野指针的形成有下面几种原因

  • 指针未初始化(未初始化,默认随机值)
  • 指针越界访问(指针指向的范围超出了原规定指向的范围)
  • 指针指向的空间释放(指函数中的变量或局部函数的空间释放,指针无法指向,造成野指针)

想要规避野指针,我们就要从根源出发

  • 指针初始化(知道指向哪里就赋值,不知道指向哪里就给指针赋值NULL
  • 小心指针越界
  • 避免返回局部变量的地址
  • 指针变量不再使用时,及时置NULL,指针使用之前检查有效性

NULL是C语言中定义的一个标识符常量,值是0,0也是地址,但这个地址是无法使用的,读写该地址会报错,就能很好的避免野指针的情况发生

assert

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

assert(p != NULL)

在代码运行到这一行的时候,会验证变量p是否等于NULL,如果不等于,程序会继续运行,否则的话会报错
assert()不仅能自动标识文件和出问题的行号,还无需修改代码就能关闭。当确定程序没问题时,在#include<assert.h>语句的前面,定义一个宏NDEBUG

#define NDBUG
#include <assert.h>

一般可以在Debug版本使用,在Relesse版本中禁用就可以

传值调用和传址调用

写一个函数,交换a和b的值

#include<stdio.h>
void swap(int a, int b)
{int t = 0;t = a;a = b;b = t;
}
int main()
{int a = 2;int b = 3;printf("%d ,%d\n",a, b);swap(a, b);printf("%d ,%d",a, b);return 0;
}

我们在main函数的内部,创建了a和b,在调用swap时将a和b传递给swap函数中的形式参数,函数中形式参数确实接受了a和b的值,但是形式参数有他们自己的地址,意思是,形式参数只是有了a和b值的参数,因为地址不一样,所以怎么改变形式参数的值和main函数中的a和b都没有关系

这就是传值调用

那么直接将a和b的地址传给swap函数不就行了

#include<stdio.h>
void swap(int * a, int * b)
{int t = 0;t = *a;*a = *b;*b = t;
}
int main()
{int a = 2;int b = 3;printf("%d ,%d\n",a, b);swap(&a, &b);printf("%d ,%d",a, b);return 0;
}

这就是传址调用
把地址传给函数就能从根本实现函数值的改变


今天的知识讲解完啦,如果觉得有用可以点一下赞和关注,也可以先收藏以防需要时找不到哦,当然如果作者写的哪里有问题欢迎指出,我们一起进步!!!

祝看到这里的人天天开心哦(笔芯)


http://www.ppmy.cn/embedded/99336.html

相关文章

逻辑回归解密:原理、公式和优化全解析

文章目录 一、 前言二、逻辑回归的原理和基本公式1. 逻辑回归的原理核心函数&#xff1a;Sigmoid函数 2. 逻辑回归模型3. 梯度上升法参数估计&#xff1a;最大似然估计对数似然函数求导过程参数更新 4. 梯度下降法参数估计&#xff1a;最小化损失函数逻辑回归的负对数似然函数梯…

ansible --limit 在指定主机执行任务

将任务只应用于指定的主机或主机组&#xff0c;而不是整个 inventory 中的所有主机。 限制单个主机 ansible-playbook -i hosts myplaybook.yml --limit "ip"限制多个主机 ansible-playbook -i hosts myplaybook.yml --limit "ip1,ip2,ip3"限制到主机组…

SpringBoot集成kafka-获取生产者发送的消息(阻塞式和非阻塞式获取)

说明 CompletableFuture对象需要的SpringBoot版本为3.X.X以上&#xff0c;需要的kafka依赖版本为3.X.X以上&#xff0c;需要的jdk版本17以上。 1、阻塞式&#xff08;等待式&#xff09;获取生产者发送的消息 生产者&#xff1a; package com.power.producer;import org.ap…

Facebook的区块链战略:如何在社交媒体中实现去中心化

随着区块链技术的发展&#xff0c;Facebook&#xff08;现Meta&#xff09;正积极探索如何将这一技术整合进其社交平台中&#xff0c;以提升用户体验和数据安全。区块链技术以去中心化、透明性和不可篡改性为特点&#xff0c;为社交媒体带来了新的可能性。本文将探讨Facebook在…

Jmeter版本下载国内外镜像源

官网最新版本 https://archive.apache.org/dist/jmeter/binaries/历史版本 https://archive.apache.org/dist/jmeter/binaries/ 国内镜像源1.阿里云 https://mirrors.aliyun.com/apache/jmeter/binaries/2.腾讯云 https://mirrors.cloud.tencent.com/apache/jmeter/

WEB应用服务器 -- Tomcat详解及案例实现

一、Web前端三大核心技术 1.1 HTML HTML&#xff08;HyperText Markup Language&#xff09;超文本标记语言&#xff0c;它不同于一般的编程语言。超文本即超出纯文本的范畴&#xff0c;例如&#xff1a;描述文本颜色、大小、字体等信息&#xff0c;或使用图片、音频、视频等…

32 - I. 从上到下打印二叉树

comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9832%20-%20I.%20%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91/README.md 面试题 32 - I. 从上到下打印二叉树…

Redis远程字典服务器(11)—— redis客户端介绍

一&#xff0c;基本介绍 前面学习的主要是各种Redis的基本操作/命令&#xff0c;都是再Redis命令行客户端&#xff0c;手动执行的&#xff0c;但是这种方式不是我们日常开发中主要的形式更多的时候&#xff0c;是使用Redis的api&#xff0c;来实现定制化的Redis客户端程序&…