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

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],也就是第一个一维数组,所以在函数传参的时候,传递的地址,是第一行这个一维数组的地址

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

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

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

相关文章

【LeetCode:2760. 最长奇偶子数组 | 模拟 双指针】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【教3妹学编程-算法题】高访问员工

2哥 : 3妹&#xff0c;今天周五怎么还下班这么晚啊&#xff1f;这么晚了才回来 3妹&#xff1a;项目快上线了&#xff0c; 最近事情比较多&#xff0c;再累也要干&#xff0c; 撸起袖子加油干&#xff01; 2哥 : 辛苦辛苦&#xff0c; 哎&#xff0c;你看到王自如格力那个采访了…

京东推出数据平台云海 API接口将达700个

1月16日消息&#xff0c;继上周面对企业用户发布京东电商云解决方案后&#xff0c;日前&#xff0c;京东云平台又发布了全新的数据开放平台——“云海”&#xff0c;以开放商家、商品、点击流等相关数据。 在京东主办&#xff0c;思路网协办的京东开放云服务合作伙伴2014峰会&…

mysql中的各种日志文件redo log、undo log和binlog

mysql中的各种日志文件redo log、undo log和binlog mysql中的各种日志文件redo log、undo log和binlog1.MySQL日志文件类型2.redo log日志2.1 作用2.2工作原理&#xff1a;2.3详解 3.undo log日志4.binlog日志5.总结 mysql中的各种日志文件redo log、undo log和binlog 1.MySQL…

【Mysql】Mysql内置函数介绍

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

解密.locked1勒索病毒:专家级策略保护您的数据免受勒索攻击

导言&#xff1a; 在当今数字化的世界中&#xff0c;勒索病毒的威胁日益严峻。.locked1 勒索病毒作为其中的一种&#xff0c;采用高级的加密算法对用户文件进行加密&#xff0c;要求支付赎金以获取解密密钥。本文91数据恢复将介绍如何面对.locked1 勒索病毒&#xff0c;有效恢…

美团外卖APP如何查看使用美团外卖红包优惠券?

美团外卖APP如何查看美团外卖红包优惠券&#xff1f; 1、手机打开美团外卖APP&#xff1b; 2、点击底部我的>我的资产>红包/神券&#xff0c;即可查看到美团外卖红包优惠券&#xff1b; 美团外卖红包优惠券怎么免费领取&#xff1f; 关注「草柴」公众号&#xff0c;回复…

【源码系列】短剧系统开发国际版短剧系统软件平台介绍

系统介绍 短剧是一种快节奏、紧凑、有趣的戏剧形式&#xff0c;通过短时间的精彩表演&#xff0c;向观众传递故事的情感和思考。它以其独特的形式和魅力&#xff0c;吸引着观众的关注&#xff0c;成为了当代戏剧娱乐中不可或缺的一部分。短剧每一集都是一个小故事&#xff0c;…

叮!您收到了一封来自达坦科技的Hackthon邀请函

DatenLord Hackathon 2023正式启动&#xff01;达坦科技基于其跨云分布式文件系统DatenLord项目&#xff0c;结合AI大模型时代背景&#xff0c;搭建了擂台&#xff0c;在此正式向您发出邀约&#xff01; 本次大赛赛题深刻有趣&#xff0c;奖品丰厚多样&#xff0c;借此机会您不…

7、使用真机调试鸿蒙项目

此处以华为手机为例&#xff0c;版本为鸿蒙4.0. 一、打开手机调试功能 1、打开开发者模式 打开“设置”—“关于手机”&#xff0c;连续点击“软件版本”可打开开发者模式 2、开启USB调试功能 打开“设置”—“系统更新”—“开发者选项”&#xff0c;下拉找到“USB调试”…

JSplacement丨随机生成置换贴图

界面很简单&#xff0c;虽然是英文&#xff0c;但基本也能看懂&#xff0c;参数调一调&#xff0c;随机生成不重复的8K高清图片。 这种图片可能对普通人感觉很奇怪&#xff0c;有什么用呢&#xff1f;会C4D建模渲染的同学应该会明白&#xff0c;特别是建一些科技类的场景背景&a…

SSL加密

小王学习录 今日摘录前言HTTP + SSL = HTTPSSSL加密1. 对称加密2. 非对称加密 + 对称加密3. 证书今日摘录 但愿四海无尘沙,有人卖酒仍卖花。 前言 SSL表示安全套接层,是一个用于保护计算机网络中数据传输安全的协议。SSL通过加密来防止第三方恶意截取并篡改数据。在实际应用…

串口通信原理及应用

Content 1. 前言介绍2. 连接方式3. 数据帧格式4. 代码编写 1. 前言介绍 串口通信是一种设备间非常常用的串行接口&#xff0c;以比特位的形式发送或接收数据&#xff0c;由于成本很低&#xff0c;容易使用&#xff0c;工程师经常使用这种方式来调试 MCU。 串口通信应用广泛&a…

034、test

之——全纪录 目录 之——全纪录 杂谈 正文 1.下载处理数据 2.数据集概览 3.构建自定义dataset 4.初始化网络 5.训练 杂谈 综合方法试一下。 leaves 1.下载处理数据 从官网下载数据集&#xff1a;Classify Leaves | Kaggle 解压后有一个图片集&#xff0c;一个提交示…

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

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

C语言指针详解(1)(能看懂字就能明白系列)文章超长,慢慢品尝

目录 1、内存和地址 2、指针简介 与指针相关的运算符&#xff1a; 取地址操作符&#xff08;&&#xff09; 解引用操作符&#xff08;间接操作符&#xff09;&#xff08;*&#xff09; ​编辑 指针变量的声明 指针变量类型的意义 指针的基本操作 1、指针与整数相加…

网申线上测评,要不要找人代做在线测评?

这是知乎上看来的问题&#xff0c;感触颇多&#xff0c;于是决定针对这个问题写个稿子&#xff0c;希望能帮助到更多人朋友。 原文如下&#xff1a;现在各大公司在招聘时通常都会采取网申发OT筛选的形式&#xff0c;但是由于难度较大&#xff0c;不少人会选择付钱找别人代做的方…

常见面试题-MySQL软删除以及索引结构

为什么 mysql 删了行记录&#xff0c;反而磁盘空间没有减少&#xff1f; 答&#xff1a; 在 mysql 中&#xff0c;当使用 delete 删除数据时&#xff0c;mysql 会将删除的数据标记为已删除&#xff0c;但是并不去磁盘上真正进行删除&#xff0c;而是在需要使用这片存储空间时…

uart控制led与beep

仲裁模块代码&#xff1a; // 外设控制模块&#xff0c;根据uart接收到的数据&#xff0c;控制led与beep的标志信号。 module arbit(input wire sys_clk ,input wire sys_rst_n ,input wire pi_flag …

交易者最看重什么?anzo Capital这点最重要!

交易者最看重什么&#xff1f;有人会说技术&#xff0c;有人会说交易策略&#xff0c;有人会说盈利&#xff0c;但anzo Capital认为Vishal 最看重的应该是眼睛吧&#xff01; 29岁的Vishal Agraval在9年前因某种原因失去了视力&#xff0c;然而&#xff0c;他的失明并未能阻…