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

news2024/11/17 5:33:48

C语言之深入指针

文章目录

  • C语言之深入指针
    • 1. 传值调用和传址调用
    • 2. 数组名的理解
    • 3. 使用指针访问数组
    • 3. ⼀维数组传参的本质

1. 传值调用和传址调用

写一个函数用来交换a b的值

传值调用:

#include <stdio.h>
void Swap1(int x, int y)
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:%d %d\n", a, b);
	Swap1(a, b);
	printf("交换后:%d %d\n", a, b);
	return 0;
}

代码运行结果如下:
在这里插入图片描述
从运行结果可以看到,a和b的值并没有进行交换,因为传给Swap1函数的只是a和b的值,在Swap1函数内部创建了a和b的临时备份,也就是将实参传给了形参,形参有自己的内存空间,对形参的修改并不会影响实参
这种函数调用方式是:传值调用

结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实

传址调用:

#include <stdio.h>
void Swap2(int* x, int* y)
{
	int tmp = 0;
	tmp = *x;
	*x = *y;
	*y = tmp;
}

int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:%d %d\n", a, b);
	Swap2(&a, &b);
	printf("交换后:%d %d\n", a, b);
	return 0;
}

在这里插入图片描述
从运行结果可以看出,a和b的值有进行交换,这是因为传给Swap2函数的是a和b的地址,然后Swap2函数用两个指针变量来储存a和b的地址,所以在函数中改变x和y的值,由于是相同地址,所以a和b的值也会改变,着这种函数调用方式是:传址调用

2. 数组名的理解

先来看段代码:

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf(" arr    = %p\n", arr);
	printf("&arr[0] = %p\n", &arr[0]);
	return 0;
}

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

从运行结果来看,arr和&arr[0]的打印出来的地址都是相同的,可以得知道,数组名就是数组⾸元素(第⼀个元素)的地址

但是有两个情况是例外

  1. • sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,
    单位是字节
  2. • &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素
    的地址是有区别的)
//情况1
#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d", sz);
	return 0;
}

在以上情况下,sizeof中的数组名是表示整个数组,计算的是整个数组的大小

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	/*int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d", sz);*/
	printf(" arr    = %p\n", arr);
	printf("&arr    = %p\n", &arr);
	printf("&arr[0] = %p\n", &arr[0]);
	return 0;
}

在这里插入图片描述

从运行结果看出,arr,&arr和&arr[0]打印的地址是一样的,都是首元素地址,arr和&arr[0]都是表示首元素的地址,那么arr和&arr有什么区别嘛
再来看一段代码:

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

运行结果如下:
在这里插入图片描述
从结果可以看出
arr + 1 从~B78 变成了 ~B7C 加上了4个字节的空间
&arr + 1从~B78 变成了 ~BA0 由于是16进制,转换为二进制就是从120变成了160 加上了40个字节的空间
&arr[0] + 1和arr + 1的结果一样,都是加上了4个字节

• 结论 arr + 1 表示跳过4个字节也就是一个元素,而&arr + 1 表示跳过40个字节,也就是一整个数组

3. 使用指针访问数组

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);  //求数组中元素的个数
	int* p = arr;
	int i = 0;
	for(i=0;i<sz;i++)
	{
		//输入10个数 以下方法都可以
		scanf("%d", p + i);
	    /*scanf("%d", arr+i);*/
	}
	for (i = 0; i < sz; i++)
	{
		//输出10个数 以下方法都可以
		printf("%d ", *(p + i)); 
		/*printf("%d ", p[i]);*/
		/*printf("%d ", *(arr + i));*/
		/*printf("%d ", arr[i]); */
		/*printf("%d ", i[arr]);*/
	}
	return 0;
}

p + i 等价于 arr + i
p [ i ] 等价于 *( p + i )
arr[ i ] 等价于 *( arr + i )
都是通过首元素的地址 + 偏移量,然后解引用来访问数组的元素
arr[ i ] 编译器会转换成 *( arr + i )来处理的,例如加法的交换律a+b可以写成b+a,那么也可以写成 *(i + arr),所以也就可以写成 i [arr],但是不建议这样写,代码的可读性极低,只是做个了解

3. ⼀维数组传参的本质

给定一共整形数组,求数组的的元素个数

#include <stdio.h>
void test1(int arr[])//参数写成数组形式,本质上是指针
{
	int sz2 = sizeof(arr) / sizeof(arr[0]);
	printf("sz2 = %d\n", sz2);
}
void test2(int* arr) //参数写成指针形式
{
	int sz3 = sizeof(arr) / sizeof(arr[0]);
	printf("sz3 = %d\n", sz3);
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz1 = sizeof(arr) / sizeof(arr[0]);
	printf("sz1 = %d\n", sz1);
	test1(arr);
	test2(arr);
	return 0;
}

代码运行结果如下:
在这里插入图片描述

1.数组名是数组⾸元素的地址;那么在数组传参的时候,传递的是数组名,也就是说本质上数组传参本质上传递的是数组⾸元素的地址
所以在函数中是无法计算数组的元素个数的
2. 其次,一维数组的传参,函数的参数可以写成数组的形式,也可以写成指针形式

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

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

相关文章

ExoPlayer架构详解与源码分析(8)——Loader

系列文章目录 ExoPlayer架构详解与源码分析&#xff08;1&#xff09;——前言 ExoPlayer架构详解与源码分析&#xff08;2&#xff09;——Player ExoPlayer架构详解与源码分析&#xff08;3&#xff09;——Timeline ExoPlayer架构详解与源码分析&#xff08;4&#xff09;—…

推荐一个Node.js多版本管理的可视化工具

关于Node.js的开发者来说&#xff0c;在开发机器上管理多个不同版本的Node.js是一个常见痛点。之前在开发者安全大全专栏中&#xff0c;提到过解决方法&#xff1a;使用nvm&#xff0c;如果对于nvm还不了解的话&#xff0c;可以前往了解。 对于TJ来说&#xff0c;因为习惯敲命…

优雅写代码之《项目规范》-附加树状图生成

阿丹&#xff1a; 最近有一些小伙伴在跳槽之后接触到了新的项目小组&#xff0c;在讨论如何整理出漂亮的项目结构以及代码书写的时候&#xff0c;既然有小伙伴发问了&#xff0c;那当然就要一起学习&#xff0c;来&#xff01;开卷&#xff01;本文章只作为一个分享&#xff0c…

nvm下载安装以及配置

1. nvm下载 nvm各版本下载链接&#xff1a;Releases coreybutler/nvm-windows GitHub 建议下载安装版的&#xff0c;非安装版还需要额外配置环境变量。 2. nvm安装 注意&#xff1a;在安装 NVM for Windows 之前卸载任何现有版本的 Node.js&#xff08;否则你会遇到版本冲突…

性能测试 —— Jmeter接口处理不低于200次/秒-场景

需求&#xff1a;期望某个接口系统的处理能力不低于200次/秒&#xff0c;如何设计&#xff1f; ①这个场景是看服务器对某个接口的TPS值是否能大于等于200&#xff0c;就可以了&#xff1b; ②系统处理能力&#xff1a;说的就是我们性能测试中的TPS&#xff1b; ③只要设计一…

电子电机行业万界星空科技MES解决方案

现在电子电机行业规模越来越大&#xff0c;也伴随着生产和管理成本走向变高的现象。针对这个问题&#xff0c;mes系统就成为各电子电机制造业的最优选择。 电子机电行业MES涵盖了从原材料采购到最终产品交付的整个过程&#xff0c;包括生产计划、物料管理、生产过程监控、质量…

【漏洞复现】浙大恩特客户资源管理系统 fileupload.jsp 任意文件上传漏洞

文章目录 前言声明一、系统概述二、漏洞描述三、资产探测四、漏洞复现五、修复建议 前言 杭州恩软信息技术有限公司客户资源管理系统fileupload.jsp接口存在安全漏洞&#xff0c;攻击者可通过上传恶意脚本应用&#xff0c;获取服务器控制权限。 声明 请勿利用文章内的相关技术…

Docker之安装mysql主从复制

安装mysql主从复制 1、新建主服务器容器实例3307 docker run -p 3307:3306 --name mysql-master \ -v /mydata/mysql-master/log:/var/log/mysql \ -v /mydata/mysql-master/data:/var/lib/mysql \ -v /mydata/mysql-master/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORDroot \…

通过cpolar实现外网ssh远程连接linux

现在我有个想法&#xff0c;就是希望通过外网能够远程连接到我的开发板。这里我们就需要使用到一种技术&#xff0c;内网穿透。 内网穿透是一种将内部网络中的设备通过外网进行访问的技术。在linux系统中&#xff0c;实现内网穿透有多种方式&#xff0c;其中最常见的方法是使用…

Spring全家桶源码解析--2.6 Spring scope 限制bean的作用范围

文章目录 前言一、Scope是什么&#xff1f;二、Scope使用2.1 单例&#xff1a;2.1.1 单例Bean的特点如下&#xff1a;2.1.2 单例设计模式 与单例bean&#xff1a; 2.2 原型bean&#xff1a;2.2.1 原型Bean的特点&#xff1a;2.2.2 原型Bean的销毁&#xff1a; 2.3 Request bean…

什么是集成测试?集成的方法有哪些?

前言 综合测试整合测试非常复杂&#xff0c;需要一些开发和逻辑技能。的确如此&#xff01;那么把这个测试整合到我们的测试策略中的目的是什么呢&#xff1f;这个问题我们先不着急回答&#xff0c;让我们一步步往下看你就知道了。 为什么要进行集成测试&#xff1f; 以下是一…

Linux项目自动化构建工具---make/Makefile

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 坚持才是硬道理&#xff01; 一、工具背景 1.会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力。 2.一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分…

达梦集群搭建

一、数据库安装 ###&#xff08;一&#xff09;安装前准备 版本准备 [rootlocalhost ~]# uname -a Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux将镜像文件传到/opt目录下 [rootlocalhost100 …

【PyQt小知识 - 1】:QLineEdit内容的更新和获取、设置无边框

文章目录 QLineEdit更新和获取文本框内容设置为无边框 QLineEdit 更新和获取文本框内容 更新&#xff1a;QLineEdit().setText(text) 获取&#xff1a;QLineEdit().text() from PyQt5.QtWidgets import * import sysapp QApplication(sys.argv)window QWidget() window.re…

sqli-labs(Less-4) extractvalue闯关

extractvalue() - Xpath类型函数 1. 确认注入点如何闭合的方式 2. 爆出当前数据库的库名 http://127.0.0.1/sqlilabs/Less-4/?id1") and extractvalue(1,concat(~,(select database()))) --3. 爆出当前数据库的表名 http://127.0.0.1/sqlilabs/Less-4/?id1") …

Java map 详解 - 用法、遍历、排序、常用API等

概要&#xff1a; java.util 中的集合类包含 Java 中某些最常用的类。最常用的集合类是 List 和 Map。 Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对&#xff08;称作“键”和“值”&#xff09;&#xff0c;其中每个键映射到一个值。 本文主要介绍java m…

金融行业如何数字化转型?_光点科技

金融行业的数字化转型涉及技术创新的引入、客户体验的改善、内部流程的优化、安全和合规性的加强以及员工技能和企业文化的转变。 技术创新 包括云计算、人工智能、大数据分析和区块链技术的采用。云计算增强数据处理的灵活性&#xff0c;AI和机器学习在风险评估和欺诈检测方面…

【技术分享】配置二层远程端口镜像案例

热门IT课程-CSDN博客文章浏览阅读24次。认证课程介绍&#xff1a;华为HCIA试听课程 &#xff1a; 华为HCIA试听课程&#xff1a;华为HCIA试听课程&#xff1a;华为HCIP试听课程&#xff1a;思科CCNA试听课程&#xff1a;思科CCNA试听课程&#xff1a;思科CCNA试听课程&#xff…

Arduino安装 esp32 by Espressif (2.0.11)

安装Arduino IDE 2.2.1 Arduino 中安装 esp32 by Espressif (2.0.11) Arduino 中安装 DS1302 库文件 2022年安装的Arduino是1.8.10版本的&#xff0c;主控芯片是外置 2MB Flash 的 ESP32-C3芯片。ESP-C3-12F-2M。 202206 Arduino软件的安装、配置与程序下载的全过程演示 2023…

plsql查询中文出现乱码

添加环境变量&#xff1a;如下 变量名&#xff1a;NLS_LANG 变量值&#xff1a;SIMPLIFIED CHINESE_CHINA.ZHS16GBK 变量名&#xff1a;TNS_ADMIN 变量值&#xff1a;D:\instantclient_11_2\network\admin 在Path中添加instantclient_11_2存放路径