当前位置: 首页 > news >正文

【C语言_指针[2]_复习篇】

目录

一、数组名的理解

二、使用指针访问一维数组中的每个元素

三、一维数组传参的本质

四、冒泡排序

五、二级指针

六、指针数组

七、指针数组模拟二维数组


一、数组名的理解

1. 一般情况下,数组名就是数组首元素的地址

2. 特殊情况1:sizeof(数组名),这里的数组名指的是整个数组,sizeof计算的结果也将是整个数组的大小

3. 特殊情况2:&数组名,这里取到的地址是整个数组的地址

4. 数组首元素的地址和数组的地址两者的区别:指针变量进行+-整数操作时,向前向后一步移动的距离是有差异的,例如下图代码,arr == &arr[0] != &arr,当arr和&arr的地址同时进行+1操作时,arr的地址移动的是4个字节,而&arr的地址移动的是40个字节。

    0x....A4 - 0x....CC = 10*16+4+1 - 12*16+12*1= -40。

5. 注意不要混淆:数组名一般情况下是数组首元素的地址函数名是函数的地址而变量名不能理解成变量的地址,它仅仅代表变量本身而已

二、使用指针访问一维数组中的每个元素

1. 请注意!指针变量本身就是地址,p == arr。如果想直接使用拿到的地址,也可以不进行把地址存入指针变量的操作,直接将地址当作指针变量进行解引用、+- 整数操作也行

2. arr[i] 的不同写法理解:.......

    ① arr[i] 本质是 *(arr+i),通过数组首元素地址偏移并解引用地址,即可找到数组中的每一位元素。

    ② [i]arr 是 *(arr+i) 交换律的产物,即 [i]arr 的本质是 *(i+arr),不过很少在代码中如此表达。

3. 总之,当我们想要访问一个数组每个元素时,可以利用数组首元素地址arr或存有数组首元素地址的指针p+ [i],表示利用数组首元素地址偏移并解引用找到地址所指向的变量,arr[i] == p[i],或写成 i[arr]==i[arr];也可以写成这种形式 *(arr+i)=*(p+i) 。

//使用指针访问一维数组中的每个元素
int main()
{int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;//数组名是数组首元素的地址,地址所指向的变量是int类型int i = 0;//循环变量for (i = 0; i < sz; i++){//一边输入,一边输出scanf("%d", p + i);printf("%d ", *(p + i));//利用地址偏移并解引用地址找到指针所指向的数组元素//写法二:利用地址直接代替指针//scanf("%d", arr + i);//printf("%d ", *(arr + i));//写法三:arr与i实行交换律的产物//scanf("%d", p + i);       //arr[i]==*(p + i)==*(arr + i)//printf("%d ", i[arr]);    //*(arr + i)==*(i + arr)==i[arr]//即arr[i]本质是*(arr+i)//即[i]arr本质是*(i+arr)}return 0;
}

三、一维数组传参的本质

1. 一维数组传参,本质上传递的是数组⾸元素的地址,而不是整个数组,也不是整个数组的地址。
2. 数组的大小只能在自己所被创建的函数中求,所以我们常常把数组的大小作为一个函数的参数一起传给自定义函数

    test(arr, sz);//sz是数组arr的大小

3. ⼀维数组传参,形参的部分的两种写法:① 直接写成数组的形式,②写成指针变量的形式,但这两种写法形参的本质都是数组首元素地址,只是有不同写法而已。

    void test(int arr[ ]); == void test(int* p);

4. 注意理解:一维数组传参属于传址调用

//在函数内部求数组的大小
//结论:数组传参本质上传递的是数组⾸元素的地址,而不是整个数组
//      数组的大小只能在自己所被创建的函数中求void test(int arr[])//现在的arr是存有数组首元素地址的指针,x86下指针的大小是4字节
{int sz2 = sizeof(arr) / sizeof(arr[2]);//这里的arr[i]==*(arr+i)表示一个整型变量//大小为4字节printf("sz2=%d\n", sz2);//打印1
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1=%d\n", sz1);//打印10test(arr);//掉用test函数求arr的大小return 0;
}
//用函数调用的方式打印一维数组中的内容//形参写法一:
void Print(int* p, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", *(p + i));}
}形参写法二:
//void Print(int arr[], int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int sz = sizeof(arr) / sizeof(arr[0]);Print(arr, sz);//将一维数组首元素的地址和数组的大小一并传给了Print函数return 0;
}

四、冒泡排序

1. 排序的趟数==元素个数-1。

2. 每趟排序结束后,下一趟最高的数组下标要在现有基础上-1。

3. 在开始冒泡排序前利用flag=1假设原本数组的排序就是最终想要的序列,如果一旦在第一趟冒泡排序中,程序没有进入到交换阶段,那么这个序列一定就是最终想要的序列,否则就继续正常进行冒泡排序。

void Bubble_sort(int arr[], int sz)
{int flag = 1;int i = 0, j = 0;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - i; j++)//趟数==元素个数-1{if (arr[j] < arr[j + 1]){flag = 0;int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}if (flag){break;}}
}void Print(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}int main()
{int arr[] = { 1, 2, 3, 4, 5, 6 ,7 ,8 ,9 ,10 };int sz = sizeof(arr) / sizeof(arr[0]);Bubble_sort(arr, sz);Print(arr, sz);return 0;
}

五、二级指针

1. 二级指针就是存放指针变量地址的指针变量

2. 对二级指针两次解引用就可以找到其对应一级指针所指向的变量

int main()
{int n = 0;int* p = &n;int** p2 = &p;//二级指针,第二颗*表示p2是一个指针变量,int*表示所指向的变量类型**p2 = 20;//*p2==p, 而*p==n,所以**p2==nprintf("%d\n", n);//打印20return 0;
}

六、指针数组

1. 指针数组就是存放指针的数组,数组中的每个元素都是指针(地址)

2. 指针数组的类型是由数组中每个指针的类型决定的

int main()
{int arr1[] = { 1, 2, 3 };int arr2[] = { 2, 3, 4 };int arr3[] = { 3, 4, 5 };int* arr[3] = { arr1, arr2, arr3 };//指针数组//由于数组名是数组首元素的地址,每个数组首元素的地址又是int*类型的//所以arr指针数组的类型是int*[3]return 0;
}

七、指针数组模拟二维数组

1. 模拟的⼆维数组,并⾮完全是⼆维数组,因为每⼀⾏的数据在内存中是⾮是连续的。

2. 下图代码的解释:parr是数组首元素的地址,而parr首元素的地址是数组arr1的地址,我们可以通过对parr+-整数拿到parr中每个元素的地址,即内部每个数组的地址,再通过对这些地址解引用拿到,每个内部数组首元素地址,最后通过首元素的地址偏移和解引用,找到parr内部数组中的每个元素,即有了 *(*(arr+i) + j) == parr[i][j] 。

int main()
{int arr1[] = {1,2,3,4,5};int arr2[] = {2,3,4,5,6};int arr3[] = {3,4,5,6,7};int* parr[3] = {arr1, arr2, arr3};int i = 0;int j = 0;for(i=0; i<3; i++){for(j=0; j<5; j++){printf("%d ", parr[i][j]);}printf("\n");}return 0;
}

相关文章:

【C语言_指针[2]_复习篇】

目录 一、数组名的理解 二、使用指针访问一维数组中的每个元素 三、一维数组传参的本质 四、冒泡排序 五、二级指针 六、指针数组 七、指针数组模拟二维数组 一、数组名的理解 1. 一般情况下&#xff0c;数组名就是数组首元素的地址。 2. 特殊情况1&#xff1a;sizeof(数…...

Rust 泛型使用过程中的 <T> 和 ::<T> 的区别

Rust 的泛型语法中&#xff0c;<T> 和 ::<T> 有不同的用途和上下文&#xff0c;但它们都与泛型有关。 <T> 在类型定义中 当你在定义函数、结构体、枚举或其他类型时&#xff0c;使用 <T> 来表示泛型参数。例如&#xff1a; fn identity<T>(x:…...

C语言 ——注释

1.1 单行注释 - 语法&#xff1a;// 待注释的内容 - 位置&#xff1a;可放在代码后&#xff0c;称之为行尾注释&#xff1b; 也可放代码上一行&#xff0c;称作行上注释。 c // 这是单行注释文字 1.2 多行注释 - 语法&#xff1a;/* 待注释的内容 */ - 注意&#xff1a;多⾏…...

C# 协程的使用

C# 中的协程是通过使用 yield 关键字来实现的&#xff0c;它们允许在方法的执行中暂停和继续。协程通常用于处理异步操作、迭代和状态机等情况。以下是关于C#协程的介绍、使用场景以及优缺点的概述&#xff1a; 介绍&#xff1a; 在 C# 中&#xff0c;协程是通过使用 yield 语…...

程序分享--C语言字母转换大小写的3种方法

关注我&#xff0c;持续分享逻辑思维&管理思维&#xff1b; 可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导&#xff1b; 有意找工作的同学&#xff0c;请参考博主的原创&#xff1a;《面试官心得--面试前应该如何准备》&#xff0c;《面试官心得--面试时如何进行自…...

jmeter发送请求参数如何使用变量

问题描述 发送jmeter请求时&#xff0c;想设置请求参数为变量 解决方法...

go go.mod file not found in current directory or any parent directory

场景&#xff1a; 安装好 liteide 之后创建了第一个 “hello world” 的golang 项目&#xff0c;却报了如下错误。 原因分析&#xff1a; go 的环境配置问题。与 golang 的包管理有关。 解决方案&#xff1a; 如果你是 Windows 系统&#xff0c;快捷键 “WinR”&#xff0c…...

K8s的kubeadm方式部署集群实例

目录 一、准备环境 主机清单 修改主机名 设置防火墙、selinux状态 主机名解析 固定ip 重启网卡 同步时间 关闭swap分区 二、获取镜像 三、安装docker 四、配置kubeadm源 安装依赖包及常用插件 1.配置kubeadm源&#xff0c;安装对应版本 2.加载相关ipvs模块 3.配…...

GRU-深度学习循环神经网络情感分类模型搭建

摘要&#xff1a; 本文详细介绍了基于GRU的深度学习循环神经网络在情感分类任务中的应用&#xff0c;涵盖基础知识回顾、功能实现、技巧与实践、性能优化与测试&#xff0c;以及常见问题解答等环节。 阅读时长&#xff1a;约30分钟 关键词&#xff1a;GRU, 深度学习, 循环神经…...

ELK日志中心搭建(六)- harbor镜像仓库

CentOS 搭建 Harbor 镜像仓库&#xff08;图文详解&#xff09;_centos harbor-CSDN博客...

初识进程状态

&#x1f30e;进程状态【上】 文章目录&#xff1a; 进程状态 发现进程的状态 运行队列 进程排队 进程状态的表述       状态在代码中的表示       运行状态       阻塞状态       挂起状态 总结 前言&#xff1a; 为了搞明白正在运行的进程是什么意思…...

线程的使用

目录 1&#xff0c;创建线程的几种方式 2&#xff0c;示例 3&#xff0c;线程常用方法 3.1 std::thread类 3.1.1 成员变量 3.1.2 thread成员函数 3.1.2.1 thread 构造函数 3.1.2.2 thread 析构函数 3.1.2.3 get_id 获取线程id 3.1.2.4 joinable 3.1.2.5 join 加入 …...

flutter选择国家或地区的电话号码区号

1.国家区号列表&#xff08;带字母索引侧边栏&#xff09; import package:generated/l10n.dart; import package:widget/login/area_index_bar_widget.dart; import package:flutter/material.dart; import package:flutter_screenutil/flutter_screenutil.dart;class LoginA…...

信号隔离器在PLC/DCS控制系统的应用

彭姝麟 Acrelpsl 概述: 随着工业自动化程度的不断提高&#xff0c;变频器也得到了非常广泛的应用。作为电力电子器件&#xff0c;变频器中要进行大功率二极管整流&#xff0c;大功率晶体管变压&#xff0c;在输入输出回路产生电流高次谐波&#xff0c;干扰供电系统、负载以及附…...

探索Linux世界:基本指令(文件查看、时间相关、grep、打包压缩及相关知识)

今天继续介绍一些指令 文章目录 1.cat - 查看文件1.1输出重定向和追加重定向1.2指令echo 2.more 指令3.less - 逐页查看文本文件内容4.head- 显示文件开头部分内容5.tail - 显示文件末尾部分内容5.1输入重定向&#xff08;<&#xff09;5.2管道&#xff08;|&#xff09; 6.…...

简单使用国产数据库—达梦

达梦数据库是一款由中国的达梦软件公司开发的关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它在业界以其高性能、可扩展性和安全性而著称。该系统广泛应用于各种应用程序的数据存储和管理&#xff0c;满足用户对于数据处理和管理的多样化需求。 安装好的达梦数…...

STM32点亮LED灯与蜂鸣器发声

STM32之GPIO GPIO在输出模式时可以控制端口输出高低电平&#xff0c;用以驱动Led蜂鸣器等外设&#xff0c;以及模拟通信协议输出时序等。 输入模式时可以读取端口的高低电平或电压&#xff0c;用于读取按键输入&#xff0c;外接模块电平信号输入&#xff0c;ADC电压采集灯 GP…...

Android UI: 自定义控件:可换行的布局控件

文章目录 继承ViewGroup重写onMeasure方法&#xff1a;计算并设置布局控件的高度重写onLayout方法&#xff1a;计算并设置每个子控件的位置具体的代码实现小结 继承ViewGroup 重写generateLayoutParams&#xff0c;设置子控件的LayoutParams为MarginLayoutParams类型 Overridep…...

Linux(Ubuntu)中安装vscode

①首先去vscode的官网下载.deb文件 网址&#xff1a;https://code.visualstudio.com/docs/?dvlinuxarm64_deb 注&#xff1a;如果linux端无法打开网页下载文件&#xff0c;可以在Windows端下载好用WinSCP传输到Linux。下载前注意下你的系统架构是arm还是amd&#xff0c;系统…...

MQTT Topic通配符

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

TJCTF 2025

还以为是天津的。这个比较容易&#xff0c;虽然绕了点弯&#xff0c;可还是把CP AK了&#xff0c;不过我会的别人也会&#xff0c;还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...