【C语言初阶】指针的运算or数组与指针的关系你了解吗?


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏:《快速入门C语言》《C语言初阶篇》

⛺️生活的理想,就是为了理想的生活!

文章目录

  • 📋 前言
  • 💬 指针运算
    • 💭 指针+-整数
    • 💭 指针-指针
    • 💭 指针的关系运算
  • 💬 指针和数组
    • 💭 指针和数组变种推演
    • 💭 指针和数组的关系
  • 💬 二级指针
      • 💬 二级指针的运算
  • 📝全篇总结

📋 前言

   🌈hello! 各位宝子们大家好啊,前面给大大家介绍了指针的基础知识。那么这一章就来给大家介绍下一部分内容!
   ⛳️指针的运算 以及 数组与指针的关系 也是我们在指针的学习过程中非常重要的!
   📚本期文章收录在《C语言初阶篇》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

🔥 注:前一章的指针讲解是《指针的概念》

💬 指针运算

💭 指针±整数

其实在上一章我们就见过指针加减整数了对于 type * p 的指针想要加 nn 是这样计算的

  • n*sizeof(type)

📚 代码演示:

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = &arr[0];
	//不用下标访问
	int sz = sizeof(arr) /sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		*p = i;
		 p = p+1;
	}
	p = &arr[0];
	for (i = 0; i < sz; i++)
	{
		printf("%d\n",*(p+i));
	}
	return 0;
}

这里我们就使用指针加减整数的方式来进行访问数组进行赋值

  • 每次让指针p 向前指4个字节,然后进行赋值!
  • 之后再把指针p 归位到最开始的指向位置进行访问
    在这里插入图片描述

前面的例子懂了我们再来看这个例子大家看看!
📚 代码演示:

#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
     *vp++ = 0;
}

这个例子其实和前面很像,数组中是从地址值向高地址使开辟的一份连续的空间!这里我们把 数组的第一个地址赋给指针 p

  • 所以指针 p 肯定没有 &values[5]的地址大!
  • p++ 每次向前指向下一个元素给每个元素赋值,直到把前五个都赋完!
    在这里插入图片描述

💭 指针-指针

指针加减整数的例子我们了解完了,下面就来了解了解指针加减指针的应用把!

  • 不知道大家了解个库函数strlen 的实现嘛/
  • 今天就用指针-指针的方法实现一下!
    🔥 注:库函数的模拟实现链接,大家感兴趣可以看看呢! 《strlen的三种实现方法》

📚 代码演示:

#include <stdio.h>
int my_strlen(char* s)
{
    char* p = s;
    while (*p != '\0')
        p++;
    return p - s;
}

int main()
{
    char arr[] = "abcdef\0";
    int len = my_strlen(arr);
    printf("%d\n", len);
	return 0;
}

⛳️ 诶这里就巧妙的应用了指针里面存放的地址来进行减法运算,用差做取值。刚好能求字符的长度的。

  • 因为一个字符也就只能只能存放一个字节
  • 而每一个字节都有地址连续的空间地址就是递增的!

💭 指针的关系运算

指针减指针的运算我们学了其实指针的运算还有一条规定:
C语言标准规定:

  • 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
  • 我们来看一下这段代码:

📚 代码演示:

for(vp = &values[5-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}

这段代码有什么问题呢?其实这段代码是倒着往回赋值的从数组 values[4],一直向后赋值但是

  • 当最后一个元素 values[0] 赋完值的时候
  • 循环调整部分 vp-- 还会执行一次导致 vp 成为野指针
  • 所以,当我们在次想用 vp 的是就需出现访问越界的问题!
    在这里插入图片描述

📚 代码改进:

for(vp = &values[5-1]; vp > &values[0];)
{
    *--vp = 0;
}

这样当指针 vp 赋完值之后就不会再进行减减的动作了。因为根本就进不来循环里面所以想前面的错误我们就避免了。
🔥 但是:这并不符合C语言的标准,所以我们尽量不要这样写以免有些编译器跑不过去。

💬 指针和数组

📚 代码演示:

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

📑 代码结果:
在这里插入图片描述

  ⛳️ 诶这里就可以看到,其实数组名和数组第一个元素的地址是一样,所以可见数组名和数组首元素的地址是一样的。

  • 那么这样写代码是可行的:
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址
//等同于 *p= &arr[0];

💭 指针和数组变种推演

而指针是用来存放地址的,数组又是一块连续的空间。所以我们可以拿指针变量来接收数组首元素的地址,用来遍历数组!

  • 所以我们对指针解引用 和 数组下标是相等的。
  •     arr[ i ] == *(p+i)
  • 而    *(i+p) == arr[ i ]
  • 所以   *(i+p) == i[ arr ]
  • 而 : p == arr == &arr[ 0 ]
  • 所以   *() 操作符 等同于 [ ]

📚 代码演示:

#include <stdio.h>
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
    int* p = arr; //指针存放数组首元素的地址
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        arr[i] = i;
        printf("%d %d %d %d\n",arr[i],i[arr],*(p+i),p[i]);
    }
    return 0;
}

📑 代码结果:
在这里插入图片描述

  • 既然这俩个操作符是相等的那么又能推演出:
  • *(arr+i) == arr[ i ] == *(i+arr)
    🔥 注:这里就不给大家演示了,大家可以自己去试着练一下呢。

💭 指针和数组的关系

  ⛳️前面我们看到了,数组和指针的应用也给大家带来不一样的数组写法是不是很有趣!那么他们究竟有什么关系?既然指针和数组使用使用起来一样的效果那么我们可以把指针理解为数组嘛?

  • 其实我们可以这样理解
  • 指针变量就是指针变量,不是数组。指针变量的大小是4/8个字节,是用来专门存放地址的.
  • 数组就是数组,不是指针,数组是一块连续的空间。可以存放一个或,多个类型相同的数据。

🔰 那么他们的联系是什么?

  • 🌱 数组中,数组名其实是数组首元素的地址,数组名 == 地址 == 指针

  • 🌱 当我们知道数组首元素地址的时候,因为数组又是连续存放的,所以通过指针就可以来遍历访问我们的数组。

💬 二级指针

  ⛳️ 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?答案是二级指针,存放指针变量的地址我们叫做二级指针!

📚 代码演示:

#include <stdio.h>
int main()
{
	int a = 10;
	int* p = &a;//p是一级指针变量,指针变量也是变量,
	//变量是在内存中开辟空间的,是变量就有地址
	int** pp = &p;//pp就是二级指针变量,
	//二级指针变量就是用来存放一级指针变量的地址
    return 0;
}

⛳️ 二级指针变量就是用来存放一级指针的地址,那么怎么来理解 int**

  • int** 第一个 int* 说明了 pp 是个指针变量
  • 而第二个 * 则说明了 pp 里面存放的是指针变量的地址
    在这里插入图片描述

💬 二级指针的运算

所以我们对 pp 指针解引用一次是找到一级指针的内容

  • 所以:*pp 等价于 p == &a

所以我们想用二级指针找到一级指针所指向的对象 a 就需要进行俩次解引用

📚 代码演示:

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

📑 代码结果:

在这里插入图片描述

📝全篇总结

✅ 归纳:
好了以上就是关于指针的运算 数组和指针的关系 以及 二级指针的概念我们就全讲解完毕了!
  指针的运算
  数组和指针的关系
  二级指针

☁️ 本章的内容就是这么多啦!不知道大家了解了没有呢?有不懂的可以私信评论嗷!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java基础教程】(四十二)多线程篇 · 上:多进程与多线程、并发与并行的关系,多线程的实现方式、线程流转状态、常用操作方法解析~

Java基础教程之多线程 上 &#x1f539;本节学习目标1️⃣ 线程与进程&#x1f50d;关于多进程、多线程、并发与并行之间的概念关系&#xff1f; 2️⃣ 多线程实现2.1 继承 Thread 类2.2 实现 Runnable 接口2.3 多线程两种实现方式的区别2.4 利用 Callable 接口实现多线程2.5 …

数学建模学习(4):TOPSIS 综合评价模型及编程实战

一、数据总览 需求&#xff1a;我们需要对各个银行进行评价&#xff0c;A-G为银行的各个指标&#xff0c;下面是银行的数据&#xff1a; 二、代码逐行实现 清空代码和变量的指令 clear;clc; 层次分析法 每一行代表一个对象的指标评分 p [8,7,6,8;7,8,8,7];%每一行代表一个…

为Android构建现代应用——设计原则

为Android构建现代应用——设计原则 - 掘金 state”是声明性观点的核心 在通过Compose或SwiftUI等框架设计声明性视图时&#xff0c;我们必须明确的第一个范式是State(状态)。UI组件结合了它的图形表示(View)和它的State(状态)。UI组件中发生变化的任何属性或数据都可以…

RuoYi-VUE : make sure to provide the “name“ option

前言 略 错误 错误原因 theme-picker 组件未被注册。 解决 src/App.vue代码恢复成若依的代码即可。&#xff08;PS&#xff1a;不知道代码被谁修改了&#xff09; 缺少这一段&#xff1a; <script> import ThemePicker from "/components/ThemePicker";…

hive基础

目录 DDL&#xff08;data definition language&#xff09; 创建数据库 创建表 hive中数据类型 create table as select建表 create table like语法 修改表名 修改列 更新列 替换列 清空表 关系运算符 聚合函数 字符串函数 substring:截取字符串 replace :替换…

C进阶:内存操作函数

内存操作函数 memcpy 头文件&#xff1a;string.h 基本用途&#xff1a;进行不相关&#xff08;不重叠的内存&#xff09;拷贝。 函数原型&#xff1a;void* memcpy(void* destination,//指向目标数据的指针 const void* source,//指向被拷贝数据的指针 size_t num);//拷贝的数…

分布式光伏电站监控及集中运维管理-安科瑞黄安南

前言&#xff1a;今年以来&#xff0c;在政策利好推动下光伏、风力发电、电化学储能及抽水蓄能等新能源行业发展迅速&#xff0c;装机容量均大幅度增长&#xff0c;新能源发电已经成为新型电力系统重要的组成部分&#xff0c;同时这也导致新型电力系统比传统的电力系统更为复杂…

【数据挖掘】时间序列的傅里叶变换:用numpy解释的快速卷积

一、说明 本篇告诉大家一个高级数学模型&#xff0c;即傅里叶模型的使用&#xff1b; 当今&#xff0c;傅里叶变换及其所有变体构成了我们现代世界的基础&#xff0c;为压缩、通信、图像处理等技术提供了动力。我们从根源上理解&#xff0c;从根本上应用&#xff0c;这是值得付…

HTML5——基础知识及使用

HTML 文件基本结构 <html><head><title>第一个页面</title></head><body>hello world</body> </html> html 标签是整个 html 文件的根标签(最顶层标签).head 标签中写页面的属性.body 标签中写的是页面上显示的内容.title 标…

实现外部缓存-Redis

目录 实现 RedisTemplate RedisTemplate的序列化 RedisSerializer 创建Redis缓存配置类 测试使用 创建配置类 创建注解测试实体 创建配置文件 创建单元测试类进行测试 实现 RedisTemplate XXXTemplate 是 Spring 的一大设计特色&#xff0c;其中&#xff0c;RedisTe…

Mybatis操作数据库执行流程的先后顺序是怎样的?

MyBatis是一个支持普通SQL查询、存储及高级映射的持久层框架&#xff0c;它几乎消除了JDBC的冗余代码。使Java开发人员可以使用面向对象的编程思想来操作数据库。对于MyBatis的工作原理和操作流程的理解&#xff0c;我们先来看下面的工作流程图。 MaBatis的工作流程 在上图中…

element的el-upload实现多个图片上传以及预览与删除

<el-form-itemlabel"实验室照片:"prop"labUrlList"v-if"ruleForm.labHave"><el-upload:action"urlUpload":headers"loadHeader"list-type"picture-card":file-list"ruleForm.labUrlList"class…

【el-tree查询并高亮】vue使用el-tree组件,搜索展开并选中对应节点,高亮搜索的关键字,过滤后高亮关键字,两种方法

第一种&#xff08;直接展开并高亮关键字&#xff09; 效果图这样的&#xff0c;会把所有的有这些关键字的节点都展开 代码&#xff1a; 这里的逻辑就是通过递归循环把所有和关键字匹配的节点筛选出来 然后通过setCheckedKeys方法把他展开选中 然后通过filterReal把关键字高亮…

数据库redis作业

数据库redis作业 redis9种数据类型的基本操作 redis持久化&#xff1a;分别启用rdb和aof&#xff0c;并查看是否有对应文件生成 作业1&#xff1a;redis9种数据类型的基本操作 1、key操作 key * #查询所有的key keys *exists 参数 #参数&#xff1a;key #判断该key是否存…

【ADS】ADS复制原理图或版图到另一个工程

直接Ctrl CCtrl V无法粘贴 可以先导入要复制的工程 加入工程&#xff0c;复制完后在勾掉工程

单独在文件中打开allure生成的index.html报告时却显示为loading

【问题描述】&#xff1a;单独在文件中打开allure生成的index.html报告时显示为loading&#xff0c;如下图&#xff1a; 【问题定位】&#xff1a;其实在allure-report下index.html文件是不能直接打开的&#xff0c;出现页面都是loading的情况&#xff0c;这是因为直接allure报…

Rust 数据类型 之 类C枚举 c-like enum

目录 枚举类型 enum 定义和声明 例1&#xff1a;Color 枚举 例2&#xff1a;Direction 枚举 例3&#xff1a;Weekday 枚举 类C枚举 C-like 打印输出 强制转成整数 例1&#xff1a;Weekday 枚举 例2&#xff1a;HttpStatus 枚举 例3&#xff1a;Color 枚举 模式匹配…

使用 Docker 快速上手官方版 LLaMA2 开源大模型

本篇文章&#xff0c;我们聊聊如何使用 Docker 容器快速上手 Meta AI 出品的 LLaMA2 开源大模型。 写在前面 昨天特别忙&#xff0c;早晨申请完 LLaMA2 模型下载权限后&#xff0c;直到晚上才顾上折腾了一个 Docker 容器运行方案&#xff0c;都没来得及写文章来聊聊这个容器怎…

wxchart 小程序 线条图不显示y轴的网格线 (分割线)

如下图&#xff1a;项目需求不显示包括x轴的6条灰色分割线。 分析&#xff1a; 看了一下源码已经写死了是5条分割线&#xff0c;加一条x轴刻度线。没给公开配置方法。 解决方案&#xff1a; 既然没有配置项目&#xff0c;可以转变思路&#xff0c;把这些线条配置成白色&…

Spring整合Mybatis原理

首先介绍一下Mybatis的工作原理 先简略的放两张图&#xff0c;后面的知识结合这两张图比较好理解 Mybatis的基本工作原理 在 Mybatis 中&#xff0c;我们可以使用⼀个接口去定义要执行sql&#xff0c;简化代码如下&#xff1a; 定义⼀个接口&#xff0c;Select 表示要执行查询…