C语言之深入指针(三)(详细教程)

news2024/11/20 15:24:13

C语言之深入指针

在学习这篇博客之前建议先看看这篇博客C语言之深入指针(二)

里面详细介绍了指针的

  1. 传值调用和传址调用
  2. 数组名的理解
  3. 使用指针访问数组
  4. ⼀维数组传参的本质

文章目录

  • C语言之深入指针
    • 1 二级指针
      • 1.1 二级指针的介绍
      • 1.2 二级指针的使用
    • 2 指针数组
      • 2.1 通过指针数组模拟二维数组
    • 3 字符指针变量
      • 3.1 常量字符串
      • 3.2 有趣的笔试题
    • 4 数组指针变量
      • 4.1 数组指针变量的创建
    • 5 二维数组的传参

1 二级指针

指针变量也是一种变量,只要是变量,在内存中就会创建一个地址给它
存放指针变量的地址的变量就是二级指针

1.1 二级指针的介绍

#include <stdio.h>
int main()
{
	int num = 10;
	int* p = &num;
	int** pp = &p;  //二级指针
	int*** ppp = &pp;//三级指针(不经常使用)
	//......
	return 0;
}

图解:
在这里插入图片描述

假设num的地址为 0x0012ff50 ,指针变量p存放了num的地址 0x0012ff50 ,同时变量p也有自己的地址 0x0012ff48 ,指针变量pp存放了指针变量p的地址 0x0012ff48 ,同时也有自己的地址,pp就是二级指针,再创建一个指针变量来存放pp的地址的话,这个指针变量就是三级指针,语法支持,同理还有四级指针,但是三级指针就不常用了,使用三级之后就没有什么必要了

1.2 二级指针的使用

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

上述代码中的**pp = 30; 等价于*p = 30; 也等价于a = 30;
**pp 先通过 *pp 找到 p,然后再对 p 进行解引用操作,即 *p ,找到 a

2 指针数组

整型数组是存放整型数据的数组
字符数组是存放字符数据的数组
那么指针数组就是存放指针的数组

int* arr[5];    //存放整型指针的数组
char* str[10];  //存放字符指针的数组
//......

2.1 通过指针数组模拟二维数组

int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };

在这里插入图片描述
二维数组在内存中是连续存放的,可以理解为是一维数组的拼接,arr[3][5]可以理解为有三个一维数组,arr[0] arr[1] arr[2] 拼接在一块组成的,每个数组中存放5个元素

那么我们就可以使用指针数组来存放arr[0] arr[1] arr[2]第地址,然后通过指针偏移来打印这三个数组,模拟实现二维数组

#include <stdio.h>
int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 2,3,4,5,6 };
	int arr3[5] = { 3,4,5,6,7 };
	int* arr[3] = { arr1,arr2,arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)//依次访问arr1,arr2,arr3
	{
		int j = 0;
		for (j = 0; j < 5; j++)//依次访问arr[i]中第一个元素至最后一个元素
		{
			printf("%d ", arr[i][j]);
			//printf("%d ", *(*(arr + i) + j));
			//*(*(arr + i) + j)等价于arr[i][j]
		}
		printf("\n");
	}
	return 0;
}

代码运行结果如下:
在这里插入图片描述
arr[i] 是访问arr数组的元素,指向了一个整型一维数组,其中 arr[i][j] 就是整型一维数组的元素
其中 arr[i] 可以写为*(arr+i) , arr[i][j] 就可以写为*(*(arr+i)+j)

3 字符指针变量

字符指针变量: char*

3.1 常量字符串

#include <stdio.h>
int main()
{
	const char* pch = "Hello World!";
	printf("%s\n", pch);
	printf("%c", "Hello World!"[6]); //打印出第七个字符 ' W '
	return 0;
}

在上述代码中:
将一串常量字符串的第一个字符的地址存到了字符指针变量中,并非整个常量字符串都存到了字符指针变量中,其次常量字符串是不可以修改的,所以我们可以使用const修饰,这样如果在下面的代码中我们修改了字符串就会提示

常量字符串可以想象成是一个字符数组,字符数组通过访问其下标来使用,常量字符串也可以通过下标来使用,上述代码中的"Hello World!"[6],就是通过下标6来打印常量字符串中的第7个元素,也就是下标为6的 ’ W ‘

3.2 有趣的笔试题

在《剑指offer》中有这么一道笔试题:

#include <stdio.h>
int main()
{
	char str1[] = "Hello World!";
	char str2[] = "Hello World!";
	const char* str3 = "Hello World!";
	const char* str4 = "Hello World!";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

代码运行结果:
在这里插入图片描述
str1 和 str2是在内存中创建的两个不同地址的字符数组 str1 和 str2指向的地址不同
而str3 和 str3 这两个字符指针变量指向一串相同的常量字符串"Hello World!",常量字符串在内存中会存储在一块相同的空间,所以str3 和 str4 指向相同的地址
str1 和 str2 都是数组名,数组名就是地址,所以在下面比较str1 和 str2的地址是不同的,所以打印not same
在3.1中提到常量字符串只有第一个字符的地址存入字符指针变量中,所以str3 和 str4 指向相同的地址 ,都是第一个字符的地址,所以打印same

4 数组指针变量

指针数组是存放指针的数组

整型指针变量 存放的是整型变量的地址 指向整型数据的指针
浮点型指针变量 存放的是浮点型变量的地址 指向浮点型数据的指针
那么数组指针变量 存放的就是数组的地址 指向数组的指针变量

4.1 数组指针变量的创建

int (*p)[10]; 

p 是一个指针变量,指向一个大小为10个整型元素的数组

由于 [ ] 操作符的优先级大于 * 操作符,我们需要用 ( ) 将指针变量括起来

int arr[10] = { 0 };
int (*p)[10] = &arr;

int  (*p)  [10]  =  &arr;
|     |   |
|     |   |
|     |   p指向数组的元素个数
|  p是数组指针变量名
p指向的数组的元素类型

5 二维数组的传参

#include <stdio.h>
void test(int arr[3][5], int x, int y)
{
	int i = 0;
	for (i = 0; i < x; i++)
	{
		int j = 0;
		for (j = 0; j < y; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	test(arr, 3, 5);
	return 0;
}

在一维数组中,函数的形参可以写为数组名也可以写为指针,那么同理二维数组的传参也可以写为数组名或者指针

#include <stdio.h>
void test(int (*arr)[5], int x, int y)
{
	int i = 0;
	for (i = 0; i < x; i++)
	{
		int j = 0;
		for (j = 0; j < y; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	test(arr, 3, 5);
	return 0;
}

二维数组是由多个一维数组组成的,二维数组的数组名也是首元素的地址,但是在二维数组中的首元素指的是arr[0][j],也就是第一个一维数组,所以在函数传参的时候,传递的地址,是第一行这个一维数组的地址

总结:⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式

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

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

相关文章

Redis持久化策略之RDB与AOF

文章目录 1.RDB1)基本介绍2)自动触发3)手动触发4)RDB文件5)优点缺点 2.AOF1)基本介绍2)使用方式3)工作流程4)重写机制5)AOF文件6)优点缺点 3.RDB AOF 我们都知道&#xff0c;redis 是一个基于内存的数据库。基于内存的好处是访问速度快&#xff0c;缺点是“不持久”——当数据…

响应数据web

get请求 package com.example.demo.controller.poio;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.*;//字符串格式返回 RestController public class ResponseBody {Req…

使用FFmpeg合并多个ts视频文件转为mp4格式

前言 爬取完视频发现都是ts文件&#xff0c;而且都是几百KB的视频片段&#xff0c;.ts 全名叫&#xff1a;MPEG Transport Stream&#xff0c;它是一个万能的多媒体容器&#xff0c;可以装下音频、视频、字幕。有时我们需要将.ts文件转换为其他更加广泛被支持的格式&#xff0…

基于Vue+SpringBoot的海南旅游景点推荐系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

pytorch单精度、半精度、混合精度、单卡、多卡(DP / DDP)、FSDP、DeepSpeed模型训练

pytorch单精度、半精度、混合精度、单卡、多卡&#xff08;DP / DDP&#xff09;、FSDP、DeepSpeed&#xff08;环境没搞起来&#xff09;模型训练代码&#xff0c;并对比不同方法的训练速度以及GPU内存的使用 代码&#xff1a;pytorch_model_train FairScale&#xff08;你真…

前端调取摄像头并实现拍照功能

前言 最近接到的一个需求十分有意思&#xff0c;设计整体实现了前端仿 微信扫一扫 的功能。整理了一下思路&#xff0c;做一个分享。 tips: 如果想要实现完整扫一扫的功能&#xff0c;你需要掌握一些前置知识&#xff0c;这次我们先讲如何实现拍照并且保存的功能。 一. windo…

Diffusion Models CLIP

Introduction to Diffusion Models 生成模型 主要指的是无监督学习中的生成模型&#xff0c;在无监督学习中的主要任务是让机器学习给定的样本&#xff0c;然后生成一些新的东西出来。比如&#xff1a;给机器看一些图片&#xff0c;能够生成一些新的图片出来&#xff0c;给机器…

element el-date-picker报错Prop being mutated:“placement“快速解决方式

报错信息 Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “placement” 报错版本 element-ui 2.15.6 和 2.15…

干扰项目成本估算精准度的5大因素

干扰项目成本估算精准度的因素有很多&#xff0c;这些因素可能导致成本估算的不准确性&#xff0c;增加成本偏差和额外的成本投入&#xff0c;从而对项目的进度和预算产生影响。因此&#xff0c;在进行项目成本估算时&#xff0c;需要充分考虑这些因素&#xff0c;并采取相应的…

NFS共享

目录 三种存储类型 作用&#xff1a; FTP文本传输协议 原理 FTP服务状态码 用户认证 常见FTP相关软件 vsftpd 软件介绍 用户和其共享目录 基础操作 安装服务端 客户端连接服务端 登录成功 匿名用户登录 1.服务端配置 2.客户端配置 3.服务端查看 匿名用户下载 删除…

Taro.navigateTo 使用URL传参数和目标页面参数获取

文章目录 1. Taro.navigateTo 简介2. 通过 URL 传递参数3. 目标页面参数获取4. 拓展与分析4.1 拓展4.2 URL参数的类型4.3 页面间通信 5. 总结 &#x1f389;欢迎来到Java学习路线专栏~Taro.navigateTo 使用URL传参数和目标页面参数获取 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x…

共聚焦显微镜的应用特点

共聚焦显微镜具有高分辨率和高灵敏度的特点&#xff0c;适用于多种不同样品的成像和分析&#xff0c;能够产生结果和图像清晰&#xff0c;易于分析。这些特性使共聚焦显微镜成为现代科学研究中不可或缺的重要工具&#xff0c;同时为人们解析微观世界提供了一种强大的手段。 作…

python递归求数字各个位数相加_和

python递归求数字的各项和&#xff0c;例如数字一千零二十四&#xff1a;“1024”&#xff0c;输出结果为“10247” 第一种方法&#xff1a; def sum(a): #求一个数字各项和&#xff0c;第一种递归方法if 0<a<9: #从前到最后一个&#xff0c;出循环…

无重复最长字符串(最长无重复子字符串),剑指offer,力扣

目录 原题&#xff1a; 力扣地址&#xff1a; 我们直接看题解吧&#xff1a; 解题方法&#xff1a; 难度分析&#xff1a; 难度算中下吧&#xff0c;这个总体不算很难&#xff0c;而且滑动窗口&#xff0c;以及哈希都比较常见 审题目事例提示&#xff1a; 解题思路&#xff08;…

windows下安装make工具

我使用的windows的gitbash命令行终端。未安装时&#xff0c;发现系统没有make命令。 make -h bash: make: command not found使用windows的包管理工具winget安装&#xff1a; winget.exe install gnuwin32.make2. 将安装的make的bin目录添加到环境变量&#xff1a; setx PATH …

HTTP Error 500.31 - Failed to load ASP.NET Core runtime

在winserver服务器上部署net6应用后&#xff0c;访问接口得到以下提示&#xff1a; 原因是因为没有安装net6的运行时和环境&#xff0c;我们可以在windows自带的 “事件查看器” 查看原因。 可以直接根据给出的地址去官网下载sdk环境&#xff0c;安装即可 下载对应的net版本…

前端反卷计划-组件库-03-组件样式

Hi, 大家好&#xff01;我是程序员库里。 今天开始分享如何从0搭建UI组件库。这也是前端反卷计划中的一项。 在接下来的日子&#xff0c;我会持续分享前端反卷计划中的每个知识点。 以下是前端反卷计划的内容&#xff1a; 目前这些内容持续更新到了我的 学习文档 中。感兴趣…

C++中静态成员变量和普通成员变量、私有成员变量和公有成员变量的区别

本文主要介绍和记录C中静态成员变量和普通成员变量、私有成员变量和公有成员变量的区别&#xff0c;并给出相关示例程序&#xff0c;最后结合相关工程应用中编译报错给出报错原因及介绍思路 一、静态成员变量和普通成员变量 C中&#xff0c;静态成员变量和普通成员变量有一些重…

SpringBoot+Vue3+MySQL集群 开发健康体检双系统

第1章 课程介绍 试看4 节 | 38分钟 观看项目演示&#xff0c;熟悉大健康体检项目主要功能。掌握学习本课程的最佳方法&#xff0c;以及如何利用在线手册学习和答疑。 收起列表 视频&#xff1a; 1-1 导学 (22:46) 试看 视频&#xff1a; 1-2 学习方法注意事项 (07:46) 视频&am…

chromium通信系统-mojo系统(一)-ipcz系统基本概念

ipcz 是chromium的跨进程通信系统。z可能是代表zero&#xff0c;表示0拷贝通信。 chromium的文档是非常丰富的&#xff0c;关于ipcz最重要的一篇官方文档是IPCZ。 关于ipcz本篇文章主要的目的是通过源代码去分析它的实现。再进入分析前我们先对官方文档做一个总结&#xff0c;…