当前位置: 首页 > 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; 往期热门专栏回顾 专栏…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...