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

C语言:指针与数组

一、. 数组名的理解

int arr[5] = { 0,1,2,3,4 };
int* p = &arr[0];

在之前我们知道要取一个数组的首元素地址就可以使用&arr[0],但其实数组名本身就是地址,而且是数组首元素的地址。在下图中我们就通过测试看出,结果确实如此。

可是我们再来看下图的结果,我们发现当我们对数组名使用sizeof函数是会发现不同之处,如果数组名就是地址,那么再x64环境下应该就是八个字节,但是却输出了20,这是为什么呢?

其实数组名就是数组首元素(第⼀个元素)的地址是对的,但是有两个例外:
1. sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小, 单位是字节。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素 的地址是有区别的)。
可以当我们试着打印这俩个地址时,看出来结果似乎是相同的。那到底是有什么区别呢,我们再想想看指针变量类型不同的区别,是否有些思路了呢。
这里我们发现arr和arr+1相差4个字节,所以&arr[0]和&arr[0]+1相差4个字节,是因为&arr [0]和 arr 都是首元素的地址,+1就是跳过⼀个元素。但是&arr 和 &arr+1相差20个字节。
因为&arr是数组的地址,+1 操作是跳过整个数组的。到这里大家应该搞清楚数组名的意义了吧。
二、使用指针访问数组
#include <stdio.h>
int main()
{int arr[5] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){scanf("%d", arr + i);}for (int i = 0; i < sz; i++){printf("%d ", *(arr + i));}return 0;
}

在scanf()中arr是arr数组首元素的地址。因为数组元素的地址是递增的,所以随着这个地址的增加,出现的地址就变成了数组中其他元素的地址了,也就是arr+i相当于&arr[i]。在打印输出时,也是相同的原理,依次取出每个元素的地址并解引用即可,也就是*(arr+i)相当于arr[i]。

三、一维数组传参的本质

#include <stdio.h>
void test(int arr[5])
{int sz1 = sizeof(arr) / sizeof(arr[0]);printf("%d ", sz1);
}
int main()
{int arr[5] = { 0 };int sz2 = sizeof(arr) / sizeof(arr[0]);test(arr);printf("%d ", sz2);return 0;
}

当我们把数组传给函数去实现求其中的元素数时,我们会发现得到的结果并不是我们想要的结果。这是为什么呢?我们接下来分析一下这段代码并想一想一维数组传参的本质。在一维数组传参中我们传的其实是这个数组的首元素的地址,所以在test()中得到的是arr这个数组中第一个元素的地址,在x64环境下它就占八个字节。而在它后面的arr[0]就像前面说的一样,相当于*arr,也就是arr数组的首元素的值,因为它的类型是int,所以占四个字节。所以一维数组传参的本质就是传递的是指针,也就解决不了求元素数的问题。当然在传参时我们也可以写成指针的形式。

#include <stdio.h>
void test(int* arr)
{int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1=%d ", sz1);
}
int main()
{int arr[5] = { 0 };int sz2 = sizeof(arr) / sizeof(arr[0]);test(arr);printf("sz2=%d ", sz2);return 0;
}

四、冒泡排序

其实冒泡排序的核心就是两两相邻元素比较。如果我们要将一个数组中的数从小到大排列就可以使用冒泡排序。

#include <stdio.h>
void bubble_sort(int* arr,int sz)
{int temp;for (int j = 1; j < sz; j++){for (int i = 1; i <= sz - j; i++){if (*(arr + i - 1) > *(arr + i)){temp = *(arr + i - 1);*(arr + i - 1) = *(arr + i);*(arr + i) = temp;}}}
}
int main()
{int arr[10] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){scanf("%d",&arr[i]);}bubble_sort(arr,sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

当然如果该数列的元素如果本来就是正序排列的,那么这样做就会很浪费效率,我们可以对程序再进行优化一下。

#include <stdio.h>
void bubble_sort(int* arr,int sz)
{int temp;for (int j = 1; j < sz; j++){int flag = 1;for (int i = 1; i <= sz - j; i++){if (*(arr + i - 1) > *(arr + i)){flag = 0;temp = *(arr + i - 1);*(arr + i - 1) = *(arr + i);*(arr + i) = temp;}}if (flag)break;}
}
int main()
{int arr[10] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){scanf("%d",&arr[i]);}bubble_sort(arr,sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

在程序中加入了flag变量,如果在第一次排序中没有改变排序,也就是这个数组的数本来就为正序,就会跳出这个循环。

五、二级指针

我们知道指针变量也是变量,那么它也应该有地址,什么能储存它呢,就是二级指针。

如图所示,pa是a的指针变量,我们对pa进行取地址,也就是我们刚才说的二级指针。

*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa *ppa 其实访问的就是 pa 。
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a 。
六、指针数组

 从名字中我们就能看出这是存放指针的数组。指针数组的每个元素都是用来存放地址(指针)的。

接下来,我们用指针数组模拟二维数组。

#include <stdio.h>
int main()
{int arr1[4] = { 1,2,3,4 };int arr2[4] = { 2,3,4,5 };int arr3[4] = { 3,4,5,6 };int* arr[3] = {arr1,arr2,arr3};for (int i = 0; i < 3; i++){for (int j = 0; j < 4; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

我们能看出来打印出的样子和二维数组一模一样。这是怎么实现呢?arr指针数组中存放的是数组名,也就是每行首元素的地址。我们打印时使用的arr[i][j]其实是通过arr[i],也就是arr+i找到是哪个小数组;再通过arr[i][j],就是*(arr[n]+j),也就是*(*(arr+i)+j)就能找出该行的每个数了。上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。

相关文章:

C语言:指针与数组

一、. 数组名的理解 int arr[5] { 0,1,2,3,4 }; int* p &arr[0]; 在之前我们知道要取一个数组的首元素地址就可以使用&arr[0]&#xff0c;但其实数组名本身就是地址&#xff0c;而且是数组首元素的地址。在下图中我们就通过测试看出&#xff0c;结果确实如此。 可是…...

win11无法检测到其他显示器-NVIDIA

https://www.nvidia.cn/software/nvidia-app/ https://cn.download.nvidia.cn/nvapp/client/11.0.1.163/NVIDIA_app_v11.0.1.163.exe 下载安装后&#xff0c;检测驱动、更新驱动。...

SQLite:DDL(数据定义语言)的基本用法

SQLite&#xff1a;DDL&#xff08;数据定义语言&#xff09;的基本用法 1 主要内容说明2 相关内容说明2.1 创建表格&#xff08;create table&#xff09;2.1.1 SQLite常见的数据类型2.1.1.1 integer&#xff08;整型&#xff09;2.1.1.2 text&#xff08;文本型&#xff09;2…...

AI工具集:一站式1000+人工智能工具导航站

在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术的飞速发展催生了众多实用的AI工具&#xff0c;但面对如此多的选择&#xff0c;想要找到适合自己的高质量AI工具却并非易事。网络搜索往往充斥着推广内容&#xff0c;真正有价值的信息被淹没其中。为了解决…...

视觉处理基础2

目录 1.池化层 1.1 概述 1.2 池化层计算 1.3 步长Stride 1.4 边缘填充Padding 1.5 多通道池化计算 1.6 池化层的作用 2. 卷积拓展 2.1 二维卷积 2.1.1 单通道版本 2.1.2 多通道版本 2.2 三维卷积 2.3 反卷积 2.4 空洞卷积&#xff08;膨胀卷积&#xff09; 2.5 …...

代码随想录第十四天|二叉树part02--226.翻转二叉树、101.对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度

资料引用&#xff1a; 226.翻转二叉树&#xff08;226.翻转二叉树&#xff09; 101.对称二叉树&#xff08;101.对称二叉树&#xff09; 104.二叉树的最大深度&#xff08;104.二叉树的最大深度&#xff09; 111.二叉树的最小深度&#xff08;111.二叉树的最小深度&#xff09;…...

vue基础之7:天气案例、监视属性、深度监视、监视属性(简写)

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…...

JS实现高效导航——A*寻路算法+导航图简化法

一、如何实现两点间路径导航 导航实现的通用步骤&#xff0c;一般是&#xff1a; 1、网格划分 将地图划分为网格&#xff0c;即例如地图是一张图片&#xff0c;其像素为1000*1000&#xff0c;那我们将此图片划分为各个10*10的网格&#xff0c;从而提高寻路算法的计算量。 2、标…...

Spring Authorization Server登出说明与实践

本章内容概览 Spring Security提供的/logout登出接口做了什么与如何自定义。Spring Authorization Server提供的/connect/logout登出接口做了什么与如何自定义。Spring Authorization Server提供的/oauth2/revoke撤销token接口做了什么与如何自定义。 前言 既然系统中有登录功…...

浏览器报错 | 代理服务器可能有问题,或地址不正确

1 问题描述 Windows连网情况下&#xff0c;浏览器访问地址显示“你尚未连接&#xff0c;代理服务器可能有问题&#xff0c;或地址不正确。”出现如下画面&#xff1a; 2 解决方法 途径1 控制面板-->网络与internet-->internet选项-->Internet属性-->连接-->…...

泷羽sec:shell编程(9)不同脚本的互相调用和重定向操作

声明&#xff1a; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…...

Milvus×OPPO:如何构建更懂你的大模型助手

01. 背景 AI业务快速增长下传统关系型数据库无法满足需求。 2024年恰逢OPPO品牌20周年&#xff0c;OPPO也宣布正式进入AI手机的时代。超千万用户开始通过例如通话摘要、新小布助手、小布照相馆等搭载在OPPO手机上的应用体验AI能力。 与传统的应用不同的是&#xff0c;在AI驱动的…...

单片机几大时钟源

在单片机中&#xff0c;MSI、HSI和HSE通常指的是用于内部晶振配置的不同功能模块&#xff1a; MSI (Master Oscillator System Interface)&#xff1a;这是最低级的一种时钟源管理单元&#xff0c;它控制着最基本的系统时钟&#xff08;SYSCLK&#xff09;&#xff0c;一般由外…...

reverse学习总结(12)

一.[FlareOn4]IgniteMe1 https://files.buuoj.cn/files/02b39b8efca02367af23aa279c81cbec/attachment.zip 根据汇编语言分析 查看需要返回为1的函数 int sub_401050() {int v1; // [esp0h] [ebp-Ch]int i; // [esp4h] [ebp-8h]unsigned int j; // [esp4h] [ebp-8h]char v4; …...

基于“微店 Park”模式下 2+1 链动模式商城小程序的创新发展与应用研究

摘要&#xff1a;本文以“微店 Park”从“开店工具”向“众创平台”的转型为背景&#xff0c;深入探讨 21 链动模式商城小程序在该平台情境下的应用潜力与创新发展路径。通过剖析“微店 Park”的运营模式&#xff0c;包括灵活承租、低成本入驻、多元流量引流等特点&#xff0c;…...

C++11:【列表初始化】【右值引用和移动语义】

目录 一.列表初始化 1.1 C98传统的{} 1.2C11中的{} 1.3C中的std::initializer_list 二.右值引用和移动语义 2.1左值和右值 2.2左值引用和右值引用 2.3引用延长生命周期 2.4左值和右值的参数匹配 2.5右值引用和移动语义的使用场景 2.5.1左值引用主要使用场景 2.5.2移…...

Zookeeper的通知机制是什么?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助&#xff1b; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper的通知机制主要通过Watcher实现&#xff0c;它是Zookeeper客…...

嵌入式蓝桥杯学习1 电量LED

cubemx配置 1.新建一个STM32G431RBT6文件 2.在System-Core中点击SYS&#xff0c;找到Debug&#xff08;设置为Serial Wire&#xff09; 3.在System-Core中点击RCC&#xff0c;找到High Speed Clock(设置为Crystal/Ceramic Resonator) 4.打开Clock Configuration &#xff0…...

bsmap输出结果解释

关于, , -, --的解释 对应着参考基因组的正链&#xff08;有义链&#xff0c;非模板链&#xff0c;即hg38的序列&#xff0c;watson链&#xff09;&#xff1b; -代表正链的互补链&#xff08;正常情况下正链的互补链是负链&#xff0c;但在重硫酸盐处理后正链和负链并不互补…...

【java-数据结构篇】揭秘 Java LinkedList:链表数据结构的 Java 实现原理与核心概念

我的个人主页 我的专栏&#xff1a;Java-数据结构&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 目录 1. Java LinkedList 基础 1.1 LinkedList 简介 1.2 LinkedList 的实现原理 1.3 LinkedList 与 ArrayList 的区别 2. 链表基础 2.1 链…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...