C语言(指针,数组和函数)

news2024/11/18 18:45:24

目录

一.指针和数组

1.指向数组

2.数组下标和指针解引用的相等性

3.*和++优先级问题

二..函数,数组和指针

1.声明数组形参

2.使用const保护地址数据

3.指针和多维数组

4.指向多维数组的指针

5.函数和多维数组

一.指针和数组

在前面的章节里面我们已经说过了,如何将申明一个指向普通数据类型的指针,就是类型名 + * + 指针名。那如何指向数组呢?我们前面说过数组是一组类型一样元素的集合,还有数组名是首元素的地址。所以我们如果想要通过指针访问和修改数组元素,只需要把数组的首元素地址给到指针,然后让指针遍历就好了

1.指向数组

之前讲过,数组元素在内存当中是连续存储的,在加上元素类型也一样。这就说明了,只要我们得到首元素地址,按照类型存储大小递增,就能不断遍历到所有元素。我们来看个例子。

这里我声名了一个int类型数组,一共有三个元素

我们重点看for循环。

里面一共有两个printf打印语句,一个负责打印数组元素的地址和值,一个负责打印p存储的地址和值。这里我们用p = p +1的方式,给p存储的地址加上特定的值(注意,这里的1不是指地址加1,而是地址加上一个int类型占用的存储字节,int是4个字节,就是32位)

我们看到结果p存储的地址和结果都是和当前num下标所指的一样的。

我们来看num[1]和num[0]地址的差值。发现只有最后两位不同。

num[0]后两位:A8  num[1]后两位: AC。

BC - B8 = 4个字节,正好是一个int类型的字节大小。

2.数组下标和指针解引用的相等性

通过上面的例子,我们可发现,

p + I = &num[i]; 具有相同的地址

*(p+i) = num[i]; 具有相同的值(*的优先级大于+号,所以必须加括号)

所以对于两种表示法都是等效的。不过如果推荐用数组表示法,因为表示起来更加的简单,明了。

3.*和++优先级问题

*的优先级大于+号,但和++优先级相同,结合律是从右往左。

我们从第二行开始

*p1++,先地址递增,然后才解引用,但要明白,地址递增只有到,序列点的时候才会生效。

*++p2;先地址递增(前++不用到,序列点就会先自增完成,这点比较特殊);

(*p3)++;先解引用p3获得值,然后在该值的基础上加1;

二..函数,数组和指针

1.声明数组形参

在上一章中,我们用int * ar这种方式传到了数组的首元素地址。这里交大家一种类似的声名

int ar[]。int * ar 和int ar[]都表示ar是指向int的指针。但是ar[]还可以更清楚的传达传送过来的是一个数组元素的想法。但int ar[]这种指针声名形式只能在函数的原型和函数定义头中可以用

在这个例子当中,我们把数组的首元素地址传入到函数当中,并且把求了所有数组元素的和total。但这里需要注意下红色括号,这里我们打印ar数据类型大小。ar是指针,不管是指向啥类型的指针,它的大小都是8个字节(也有可能是4个字节)

 

2.使用const保护地址数据

如果我们想处理一个基本类型时,我们可以选择传递类型变量值或类型变量的地址。但放在数组身上就不行,对于数组,必须要传递地址到函数中。(因为只能靠地址,才能在函数中处理到数组的所有数据)

这个时候const的作用就到了。这里const位置不同,所造成的效果也不同

1: 开头

Const int * ar

ar指针所指向内容的值无法修改,但可以修改ar指向的地址

2:后面

Int * const ar

ar指针指向的地址无法修改,但地址的值可以修改

3:前面后面都有

Const int * const ar

ar指针指向的地址无法修改,且地址的值也无法修改

这里要记住

1.可以把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的(保证赋值过来地址上面的值都不会被修改)

2.非const数据只能赋给普通指针(如果把cosnt数据给到一个普通指针,那么指针就可以对该地址上面的值进行修改)

可以发现系统不会让你修改x,z存储地址上的值

这里可以看到系统不允许你修改指向x存储的值

3.指针和多维数组

Int zippo[4][2]

我们来对zippo进行详细讲解

1.因为zippo是数组首元素的地址,所以zippo的值和&zippo[0]的值相同。而zippo[0]本身是一个内含两个整数的数组,所以zippo[0]的值和它首元素(一个整数)的地址(&zippo[0][0]的值)相同。

简而言之,zippo[0]是一个占用一个int大小对象的地址,而zippo是一个占用两个int大小对象的地址。

由于这个整数和内含两个整数的数组都开始于同一个地址,所以zippo和zippo[0]的值相同

2.给指针或地址加1,其值会增加对应类型大小的数值。在这方面,zippo和zippo[0]不同,因为zippo指向的对象占用了两个int大小。而zippo[0]指向的对象只占用一个int大小。

所以,zippo + 1 和 zippo[0] + 1值不同

3.解引用一个指针或在数组名后使用带下表的【】运算符,得到引用对象代表的值。

因为zippo[0]是该数组首元素(zippo[0][0])的地址,所以*(zippo[0])表示存储在zippo[0][0]位置上的值

*zippo代表该数组首元素(zippo[0])的值,但是zippo[0]本身是一个地址。该地址是&zippo[0][0],所以*zippo就是&zippo[0][0]。所以**zippo与*&zippo[0][0]等价。

所以简而言之,zippo是地址的地址,必须解引用两次才能获得原始值,地址的地址或指针的指针就是双重间接

代码源码:

#include <stdio.h>

int main(){

    int zippo[4][2] = {{2,4},{6,8},{1,3},{5,7}};

    printf("  zippo = %p     zippo+1 = %p\n",zippo,zippo + 1);          //zippo + 1 在原地址的基础上加两个int类型,8byte

    printf("  zippo[0] = %p  zippo[0]+1 = %p\n",zippo[0],zippo[0] + 1); //zippo[0] + 1 在原地址的基础上加一个int类型,4byte

    printf("  *zippo = %p     *zippo+1 = %p\n",*zippo,*zippo + 1);      //*zippo + 1,*zippo相当于zippo[0][0],所以加1,加一个int类型,4byte

    printf("zippo[0][0] = %d\n",zippo[0][0]);

    printf("*zippo[0] = %d\n",*zippo[0]);   //zippo[0]地址为zippo[0][0]

    printf("**zippo = %d\n",**zippo);       //*zippo值为&zippo[0][0],所以**zippo等于zippo[0][0]的值

    printf("    zippo[2][1] = %d\n",zippo[2][1]);

    printf("*(*(zippo + 2) + 1) = %d\n",*(*(zippo + 2) + 1));   //zippo+2相当于zippo[0] + 2,等于zippo[2],*zippo[2]等于1的地址,然后加+1,

    //得到zippo[2][1],然后在解引用,*zippo[2][1]等于3

    return 0;

}

4.指向多维数组的指针

Int (* pz)[2];

pz指向一个内含两个int类型值得数组

Int * pz[2];

pz是一个内含两个指针元素得数组,每个元素都指向int得指针

([]优先级高于*)

效果和上面数组下标结果一致。

5.函数和多维数组

前面我们已经学习了如何多维数组,那么这一节当中我们将学习如何使用指针在函数当中处理多维数组。

这里我用红色形式声明了函数的一个数组中有两个元素,每个元素都有2个int类型的值。黄色部分,意思表示为存储两个int类型元素的数组。通过row控制数组的移动。

先看num[3][2],这里就比较明显了,但日常使用来说我们用的不同,因为这样的形参不能很好的表示其是一个指针。而在使用的时候,我们直接传入数组名就好了。或者&num都可以。用&num可以更好表示,变量的值是一个数组且数组中有三个元素,每个元素都有2个int类型的值。

而num[][2]就是上面我们所说的用的最多的一种方式。它能够最直接的表达出我们想传递一个数组指针的想法。

而看到下面两个函数中,下划线部分。我们使用*(*(num + i) + j);的方式获取地址上面的值。*(num + i)是确定第几个数组。然后在 + j 在解引用获得数组的第几个元素值。


好了朋友们我们今天的内容到这就结束了,今天的内容到这里就结束了,如果有啥不会的朋友记得论坛里面提问哈~

如果朋友你感觉文章的内容对你有帮助,可以点赞关注文章和专栏以及关注我哈,嘿嘿嘿我会定期更新文章的,谢谢朋友你的支持哈

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

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

相关文章

Mr. Cappuccino的第39杯咖啡——Kubernetes之深入理解Pod

Kubernetes之深入理解PodPod相关概念Pod详细配置清单Pod核心配置Pod基本配置1. 创建yaml文件2. 创建namespace并根据yaml文件创建资源3. 查看namespace下的pod列表以及pod的详细信息Pod中多个容器的名称和端口号不能相同Pod镜像拉取策略Pod环境变量Pod端口相关设置Pod资源相关配…

echarts修改饼图,环形图的圆环宽度,大小

echarts修改环形图的圆环宽度&#xff0c;大小 环形图圆环的大小需要通过series-pie. radius属性来修改 radius 饼图的半径。 Array.<number|string>&#xff1a;数组的第一项是内半径&#xff0c;第二项是外半径。每一项遵从上述 number string 的描述。 把数组的第…

前端高频面试题—JavaScript篇(四)

&#x1f4bb; 前端高频面试题—JavaScript篇&#xff08;四&#xff09;&#x1f3e0;专栏&#xff1a;前端面试题 &#x1f440;个人主页&#xff1a;繁星学编程&#x1f341; &#x1f9d1;个人简介&#xff1a;一个不断提高自我的平凡人&#x1f680; &#x1f50a;分享方向…

150家半导体企业IPO最新进展(附企业名录)

前言 根据Omdia的数据显示&#xff0c;2022年全球在第一季度、第二季度、第三季度实现的半导体收入分别为1593亿美元、1581亿美元、1470亿美元&#xff0c;分别环比下降0.03%、1.9%、7.0%。 目前&#xff0c;半导体产业链经历了自2022上半年的欣欣向荣&#xff0c;到2022年下半…

万字长文掌握Python高并发

文章目录0 前言1 并发、并行、同步、异步、阻塞、非阻塞1.1 并发1.2 并行1.3 同步1.4 异步1.5 阻塞1.6 非阻塞2 多线程2.1 Python线程的创建方式2.1.1 方式一2.1.2 方式二 继承Thread2.1.3 通过线程池创建多线程2.2 聊聊GIL2.2.1 Python线程与操作系统线程的关系2.3 线程同步2.…

【CICD】Jenkins 部署 Docker 容器形态的后端服务

在实现 Jenkins 构建部署前端项目之后&#xff0c;逐渐对使用 Jenkins 部署后端服务有了一定兴趣&#xff1b;总体流程没有什么很大的变化&#xff0c;不过是后端服务需要以 Docker 的形式进行启动&#xff0c;在此记录一下具体过程&#xff08;部分过程与构建部署前端相同不做…

windows下载安装jdk1.8(jdk8)基础篇

一、前言 目前jdk最高升级到JDK19版本了&#xff0c;但是大部分应用系统都是用的1.8&#xff0c;对于初学者来说&#xff0c;也需要下载安装这个版本的jdk。 二、下载安装步骤 一、我已经下载下来&#xff0c;大家到【我的下载目录】下载&#xff0c;密码3360&#xff0c;分…

使用Benchto框架对Trino进行SQL性能对比测试

有时需要对魔改源码前后的不同版本Trino引擎进行性能对比测试&#xff0c;提前发现改造前后是否有性能变差或变好的现象&#xff0c;避免影响数据业务的日常查询任务性能。而Trino社区正好提供了一个性能测试对比框架&#xff1a;GitHub - trinodb/benchto: Framework for runn…

金额大写转换

金额大写转换&#xff08;C语言 &#xff09; 本人喜欢探索各种算法。见站内好多此类文章&#xff0c;有些很好&#xff0c;有些不完整。姑且也来凑下热闹。 金额大写应用在很多方面&#xff0c;如支票、发票、各种单据&#xff0c;各种财务凭证&#xff0c;合同文本金额部分。…

【逐步剖C】-第七章-数据的存储

一、数据类型介绍 1. C语言基本内置类型&#xff1a; char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更长的整形 float //单精度浮点数 double //双精度浮点数2. 类型的基本归类 &#xff08;1&#xff09;整型&#xff1a; charunsign…

c语言指针

指针 指针是存放地址的变量&#xff0c;也可以说指针地址。 对于定义p&#xff08;这里的话&#xff0c;只是定义&#xff0c;说明p是指针&#xff09;&#xff0c;p作为一个指针去指向存放数据的位置&#xff0c;而p意思是取&#xff08;p指向的内存位置的数据&#xff09;&…

es启动,浏览器无法访问9200

通过brew成功启动es&#xff0c;但是访问http://localhost:9200/报错&#xff0c;连接被拒绝 %:brew services start elasticsearch-full> Successfully started elasticsearch-full (label: homebrew.mxcl.elasticsearc可能原因如下&#xff1a; 1、安装java 要先安装ja…

聊聊async/await原理

前言 我们知道Promise的出现极大地解决了回调地狱&#xff0c;但是如果使用流程非常复杂的话&#xff0c;就非常容易过多地调用Promise的then()方法&#xff0c;这样也不利于使用和阅读。 例如&#xff1a;我希望在请求 www.baidu.com 后输出请求的结果&#xff0c;再去请求 …

【基于腾讯云的远程机械臂小车】

1. 项目来源 项目源码地址&#xff1a;https://gitcode.net/VOR234/robot_arm_car/-/blob/master/TencentOS-tiny123.zip https://gitee.com/vor2345/robot_arm_car 程序分别 视频演示&#xff1a;https://www.bilibili.com/video/BV15M4y1D7MD/?vd_source530bf85167de80ff…

46.在ROS中实现global planner(2)

前文实现了一个global planner的模板&#xff0c;并且可以工作&#xff0c;本文将实现astar算法&#xff0c;为后续完成一个astar global planner做准备 1. AStar简介 1.1 AStar Astar算法是一种图形搜索算法,常用于寻路。Astar算法原理网上可以找到很多&#xff0c;简单的说…

企业/品牌新闻稿怎么写?

撰写出优质的企业/品牌新闻稿对于任何一个希望通过新闻媒体推广自己品牌的公司来说都是十分重要的。在新闻稿中&#xff0c;您可以通过介绍自己的公司&#xff0c;披露最新的产品和服务信息以及宣传最新的成就来吸引媒体和读者的关注。下面是一些关于如何撰写出优质的企业/品牌…

【工具篇】Firmwalker车联网实用小工具介绍

前言 firmwalker这个小工具在工作中也一直在用&#xff0c;正好领导说要写一篇这个工具的分析说明文章&#xff0c;经过询问可以发表博客。由于一直在用&#xff0c;所以末尾优劣势部分存在一些主观想法。 编写不易&#xff0c;如果能够帮助到你&#xff0c;希望能够点赞收藏加…

SpringCloud, SpringCloud-Alibaba,Nacos概述

目录 SpingCloud概述 1.SpringCloud是什么? 2.SpringCloud和SpringBoot的关系 3.SpringCloud-Alibaba概述 3.1.Netflix公司项目进入维护模式 3.2.Spring Cloud Alibaba是什么&#xff1f; 3.3.Spring Boot和Spring Cloud的版本号说明 3.Nacos总结 SpingCloud概述 1.Spri…

蓝桥杯刷题——基础篇(一)

这部分题目&#xff0c;主要面向有志参加ACM与蓝桥杯竞赛的同学而准备的&#xff0c;蓝桥杯与ACM考察内容甚至评测标准基本都一样&#xff0c;因此本训练计划提供完整的刷题顺序&#xff0c;循序渐进&#xff0c;提高代码量&#xff0c;巩固基础。因竞赛支持C语言、C、Java甚至…

【JAVA八股文】算法、数据结构、基础设计模式

算法、数据结构、基础设计模式1. 二分查找2. 冒泡排序3. 选择排序4. 插入排序5. 希尔排序6. 快速排序7. ArrayList8. Iterator9. LinkedList10. HashMap1&#xff09;基本数据结构2&#xff09;树化与退化3&#xff09;索引计算4&#xff09;put 与扩容5&#xff09;并发问题6&…