指针的进阶(1)

指针的回顾

在C语言中,指针是一个变量,与其他数据不同的是,它的作用是用来存储其它变量的内存地址。指针可以指向不同类型的数据,包括整数、浮点数
、字符、数组等。通过使用指针,我们可以直接访问和修改存储在内存中的数据,而不需要进行复制或者传递大量的数据。
这是指针的大概情况,下面就要对指针进一步研究。

字符指针

对于字符来说,我们可以用char类型来创建变量,那么就有char*类型的指针,通常我们称之为字符指针。
先看以下代码:

int main()
{
 char ch = 'w';
 char *pc = &ch;
 *pc = 'w';
 return 0;
}
创建一个字符变量ch,字符指针pc指向ch的地址,对pc解引用就是'w'。

这是常规的用法,但在大多数情况下,以下情况更加普遍使用:

int main()
{
 const char* pstr = "hello cc.";
 printf("%s\n", pstr);
 return 0;
}
在这里,打印出来的就是“hello cc",但pstr存的是字符串的首元素地址
,也就是说,对ptsr解引用,得到的是'h'。

在这里插入图片描述
在这里,会发现我在指针pstr加入了const,这是因为字符串的地址本来就不可改变,加上const,增加程序的可读性和维护性。看下面例子:

#include <stdio.h>
int main()
{
 char str1[] = "hello cc.";
 char str2[] = "hello cc.";
 const char *str3 = "hello cc.";
 const char *str4 = "hello cc.";
 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和str4,它们是字符指针,相当与常量字符串自己开辟了空间,然后两个指针都会指向内容相同的字符串首元素
在这里插入图片描述

指针数组

顾名思义,它是一个数组,只是每个数组里面存放的是指针;
在这里插入图片描述
我们可以用指针数组实现二维数组

int main()
{
	int arr1[] = { 1,2,3,4,5 };//arr1 - int*
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	//指针数组
	int* arr[3] = { arr1, arr2, arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在这里插入图片描述
对于一维数组来说,本质上就是一维指针,也就是arr1 类型为int*.

数组指针

指针的定义

数组指针,是一个指针,指向数组的指针。

int *p1[10];//指针数组
int (*p2)[10];//数组指针

在这里插入图片描述
这里要注意:[]的优先级要高于号的,所以必须加上()来保证p先和结合。

&数组名VS数组名

int arr[10];

我们知道,arr是指首元素地址,&arr指的是整个数组的地址;

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
 	printf("%p\n",&arr);
	return 0;
}

在这里插入图片描述
上面虽然的地址都是一样,这是因为刚好都指向了首元素地址
在这里插入图片描述

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);//
	printf("%p\n", arr+1);//

	printf("%p\n", &arr[0]);//
	printf("%p\n", &arr[0]+1);//

	printf("%p\n", &arr);//
	printf("%p\n", &arr+1);//

	
	return 0;
}

在这里插入图片描述

但我们把16进制转换为10进制后&arr+1就增加了40个bit,但arr+1相对于arr只增加了4bit
在这里插入图片描述

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址.

数组指针的使用

直接看以下代码:

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

在这里插入图片描述
对于一维数组来说,数组名表示首元素地址,而二维数组中,首元素表示的是第一行的地址,所以把数组指针看作是二维数组中,指向一维数组的指针。也就是所,二维数组可以由数组指针来表示。

数组参数、指针参数

一维数组传参

#include <stdio.h>
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int *arr[20])
{}
void test2(int **arr)
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

对于以上所有test函数来说,所有形式参数都是可以接收到实参的;数组本质来说就是指针,所以可由指针来接收;而指针数组来说,就要用二维指针来接收。

二维数组传参

void test(int arr[3][5])
{}
void test(int arr[][5])
{}
//对于二维数组来说,行的数字可以省略,列的数字不能省略
void test(int *arr)
{}
void test(int (*arr)[5])
{}
//数组指针是可以的,但对于指针数组来说,数组中包含的是指针,虽然说
//数组本质就是指针,但是由于数组的限制,指针的地址可能会出现连续的
//状态,无法确定一行中有多少列,故不可使用。

一级指针传参

#include <stdio.h>
void print(int *p, int sz)
{
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d\n", *(p+i));}
}
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9};
 int *p = arr;
 int sz = sizeof(arr)/sizeof(arr[0]);
 //一级指针p,传给函数
 print(p, sz);
 return 0;
}

对于数组来说,元素的地址是连续存在的,所以可以用指针叠加的方式进行循环遍历。

二级指针传参

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

num=10
num=10

对于实参来说,只要是一级指针的地址,就可以传参,而函数中的形参一般只用二级指针接收即可。

总的来说,对于数组传参,形参部分可以是指针,也可以是数组;
而对于指针传参,实参部分只要是地址,都可以当作实参,形参只用指针来接收。

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

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

相关文章

Zabbix 的使用

Zabbix 的使用 一、添加 zabbix 客户端主机1.1 环境准备1.2 服务端和客户端都配置时间同步1.3 服务端和客户端都设置 hosts 解析1.4 设置 zabbix 的下载源&#xff0c;安装 zabbix-agent21.5 修改 agent2 配置文件1.6 启动 zabbix-agent21.7 在服务端验证 zabbix-agent2 的连通…

Android Studio实现内容丰富的安卓校园新闻浏览平台

如需源码可以添加q-------3290510686&#xff0c;也有演示视频演示具体功能&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号070 1.开发环境 android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看新闻列表…

【爬虫】百度FengXiangBiao(完全爬虫卡住了,是爬虫+文本提取方式)

学习使用。爬虫有风险。使用需谨慎。切记切记。 参考链接&#xff1a;学习python爬虫—爬虫实践&#xff1a;爬取B站排行榜 都是排行榜反正 网页细节 按F12&#xff0c;打开控制台。前端就是这点好&#xff0c;非常直观。 找到排行的具体位置&#xff0c;如下图&#xff0c;这…

【如何成功加载 HuggingFace 数据集】不使用Colab,以ChnSentiCorp数据集为例

【如何成功加载 HuggingFace 数据集】不使用Colab&#xff0c;以ChnSentiCorp数据集为例 前置加载数据集尝试一&#xff1a;标准加载数据库代码尝试二&#xff1a;科学上网尝试三&#xff1a;把 Huggingface 的数据库下载到本地尝试3.5 创建 state.json彩蛋 前置 Huggingface …

找不到 配置管理器。sql server 2008 r2 在win10下

win10 打开sqlserver2008r2的SQL Server 配置管理器 &#xff0c;通过开始程序中找不到“SQL Server 配置管理器”。去自己电脑上此目录找&#xff0c;“C:\Windows\SysWOW64\SQLServerManager10.msc”&#xff0c;直接运行此文件就可以调出“SQL Server 配置管理器”。 在win1…

c语言内存

程序是保存在硬盘中的&#xff0c;要载入内存才能运行&#xff0c;CPU也被设计为只能从内存中读取数据和指令。 对于CPU来说&#xff0c;内存仅仅是一个存放指令和数据的地方&#xff0c;并不能在内存中完成计算功能&#xff0c; 如&#xff1a;计算abc,必须将a,b,c都读取到CPU…

CodeMirror 对 XML 文档熟悉及元素控制自定义

CodeMirror 是一个网络代码编辑器组件。它可以在网站中用于实现支持多种编辑功能的文本输入字段&#xff0c;并具有丰富的编程接口以允许进一步扩展。 本文为 xml 格式的代码提示约束格式规范的自定义示例内容。 先看效果&#xff0c;如下&#xff1a; 官方 Demo 的完整代码如…

十八、Jenkins(centos7)执行接口自动化测试脚本,飞书推送测试结果消息

十八、Jenkins&#xff08;centos7&#xff09;执行接口自动化测试脚本&#xff0c;飞书推送测试结果消息 1.创建 Freestyle project 项目 2. 输入git仓库地址 https://gitee.com/HP_mojin/pytest_allure_request_20220811 3. 增加构建步骤-Execute shell&#xff08;Jenkins…

怎样做好客户自助服务?

在当前高速发展的信息化时代&#xff0c;人们已经习惯了即时满足的方式。对于品牌来说&#xff0c;当客户遇到问题时&#xff0c;他们希望能够获得即时细致的解答。如果客户需要等待很长时间才能获取答案&#xff0c;他们的满意度就会降低。因此&#xff0c;企业是否提供客户自…

Java - 异常处理

异常介绍 对异常进行捕获&#xff0c;保证程序可以继续运行&#xff0c;提升程序的健壮性。 执行过程中所发生的异常时间可分为两大类&#xff1a; Error&#xff1a; Java虚拟机无法解决的严重问题。如&#xff1a;JVM系统内部错误&#xff0c;资源耗尽等严重情况。比如&…

mysql的一些练习题

1. 第1题 mysql> create database Market charset utf8; Query OK, 1 row affected (0.01 sec)第二题 mysql> use Market Database changed mysql> mysql> create table customers(-> c_num int(11) primary key auto_increment,-> c_name varchar(50),-&…

mac怎么把m4a转换成mp3?

mac怎么把m4a转换成mp3&#xff1f;大家都知道m4a是苹果公司专属的音频文件格式&#xff0c;因此它是可以直接在mac电脑上打开播放的&#xff0c;但这并不代表m4a音频文件可以在其他播放器或者播放设备上直接打开和使用&#xff0c;相信这个问题大家都遇到过&#xff0c;造成这…

黑马头条-day02

文章目录 前言一、文章列表加载1.1 需求分析1.2 表结构分析1.3 导入文章数据库1.4 实现思路1.5 接口定义1.6 功能实现 二、freemarker2.1 freemarker简介2.2 环境搭建&&快速入门2.2.1 创建测试工程 2.3 freemarker基础2.3.1 基础语法种类2.3.2 集合指令2.3.3 if指令2.3…

使用LiteSpeed缓存插件将WordPress优化到100%的得分

页面速度优化应该是每个网站所有者的首要任务&#xff0c;因为它直接影响WordPress SEO。此外&#xff0c;网站加载的时间越长&#xff0c;其跳出率就越高。这可能会阻止您产生转化并为您的网站带来流量。 使用正确的工具和配置&#xff0c;缓存您的网站可以显着提高其性能。因…

【Spark_BigData】期末复习考试——

复习题目 yarn框架中不包含的进程为 Yarn包括两个主要进程:资源管理器Resource-Manager,节点管理器Node-Manager。 Scheduler zookeeper spark SQL 前身 Shark 在Spark中,DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。 HiveContext继承自SQLCon…

Jvisualvm内存模型剖析-JVM(五)

上篇文章代码讲解了tomcat加载以及gc回收流程。 Jvm内存模型剖析优化-JVM&#xff08;四&#xff09; Jvisualvm 我们可以编写如上代码&#xff0c;之后打开jvm自带的工具jvisualvm。 如果我们看visual不会明显变化&#xff0c;则可以修改睡眠参数&#xff0c;时间改小。 当…

Vue中的el-date-picker时间选择器的使用

1、value-format属性设置需要什么格式的时间 2、type类型选择datetime、date 年月日时分秒 <el-date-pickervalue-format"yyyy-MM-dd HH:mm:ss"v-model"excelRuleForm.startTime"type"datetime":placeholder"选择开始时间"> &…

【尚医通】vue3+ts前端项目开发笔记——项目分析

尚医通开发笔记 一、项目分析 项目在线地址&#xff1a;http://syt.atguigu.cn测试帐号&#xff1a;17720125002 首页 home header 全局组件布局 左&#xff1a;logo 、title中&#xff1a;初始隐藏 搜索框 公共组件显示条件&#xff1a;在页面滚动到页面内搜索框的位置显示…

爬虫入门04——requests库中的User-Agent请求头

import requests#定义请求的url url https://www.baidu.com/ #https://site.ip138.com/www.xicidaili.com/#发起get请求 res requests.get(url url)#获取响应结果#响应对象 print(res)#获取响应状态码 print(res.status_code)#获取响应数据 print(res.text) #返回的是字符…

mysql 关于用户的练习

环境&#xff1a; (1) 创建用户 create user account1localhost identified by oldpwd1; 授予权限&#xff1a; #给表授予权限 grant select,insert on Team.player to account1localhost identified by oldpwd1;#给info字段授予update权限 grant update(info) on Team.pl…