C 练习实例77-指向指针的指针-二维数组

关于数组的一些操作

#include<stdio.h>
#include<stdio.h>
void fun(int b[],int length)
{for(int i=0;i<length;i++){printf("%d ",b[i]);}printf("\n");for(int i=0;i<length;i++){	//数组作为形参传递,传递的是指针,所以能够改变值b[i]++;}
}
int main()
{int a[5]={1,2,3,4,5};
//	int b[5]=a;  不合法,数组的本质是常量指针,不允许被修改
//	也就是说b指向了一片空间,这片空间是随机分配的,它一辈子只能指向那片空间fun(a,sizeof(a)/sizeof(int));for(int i=0;i<sizeof(a)/sizeof(int);i++){printf("%d ",a[i]);}printf("\n");return 0;
}

运行结果

1 2 3 4 5
2 3 4 5 6

指向指针的指针

代码 

#include<stdio.h>
int main()
{int a=100;int *p1=&a;int **p2=&p1;printf("&a=%p\n",&a);printf("p1=%p\n",p1);printf("*p2=%p\n",*p2);printf("a=%d\n",a);printf("*p1=%d\n",*p1);printf("**p2=%d\n",**p2);return 0;
}

 结果

&a=000000000065FE14
p1=000000000065FE14
*p2=000000000065FE14
a=100
*p1=100
**p2=100

二维数组

代码

#include<stdio.h>
int main()
{
//	要点:数组名可以当指针用,它的值就是首地址,它指向的就是数组首元素int b[3]={1,2,3};//一维数组printf("b=%p\n",b);//首地址printf("&b=%p\n",&b);//首地址printf("&b[0]=%p\n",&b[0]);//首地址printf("*b=%d\n",*b);//首地址可以取出首元素printf("b[0]=%d\n",b[0]);printf("\n");/*二维数组的每一行其实就是一个一维数组a[0]可以认为是第一行数组的数组名,也可以认为是指向第一行数组的指针a[0]的值实际上就是第一行数组的首地址以此类推,a[1]是第二行,a[2]是第三行......*///	{a[0],a[1],a[2]}也可以看作是一个一维数组,a是它的名,也可以看作是指针
//	a的值就是就是一维数组a[0]的首地址int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};//二维数组printf("a[0]=%p\n",a[0]);//第一行数组的首地址,也就是首地址printf("&a[0]=%p\n",&a[0]);//第一行数组的首地址,也就是首地址printf("*a=%p\n",*a);//第一行数组的首地址,也就是首地址printf("a=%p\n",a);//第一行数组的首地址,也就是首地址printf("&a=%p\n",&a);//第一行数组的首地址,也就是首地址printf("&a[0][0]=%p\n",&a[0][0]);//第一行数组的首地址printf("a[0][0]=%d\n",a[0][0]);//首元素printf("*a[0]=%d\n",*a[0]);//首地址可以取出首元素printf("**a=%d\n",**a);//首地址的首地址可以取出首元素-指针的指针return 0;
}

运行结果

b=000000000065FE14
&b=000000000065FE14
&b[0]=000000000065FE14
*b=1
b[0]=1a[0]=000000000065FDE0
&a[0]=000000000065FDE0
*a=000000000065FDE0
a=000000000065FDE0
&a=000000000065FDE0
&a[0][0]=000000000065FDE0
a[0][0]=0
*a[0]=0
**a=0

在一维数组中,a的值=&a的值=&a[0]的值,*a=a[0]

在二维数组中,&a=a=*a=a[0]=&a[0]=&a[0][0],a[0][0]=*a[0]=**a[0],有点绕哈,是不是和指向指针的指针有点像。

数组指针(指向数组的指针)

它的定义如下:

#include <stdio.h>
int main()
{int a[3]={1,2,3};int *p=a;printf("*p+0=%d\n",*p+0);printf("*p+1=%d\n",*p+1);printf("*p+2=%d\n",*p+2);
}

输出结果

*p+0=1
*p+1=2
*p+2=3

数组指针,就是指向数组的指针,它存放的是数组的首地址,每加1其实是加了一个int类型的字节长度。

指针数组

指针数组,就是数组的每个元素是指针类型的,存放的是地址值。

#include <stdio.h>
int main()
{int a=1;int b=2;int c=3;printf("%d,%d,%d\n",&a,&b,&c);int *array[3]={&a,&b,&c};
//int *->int型指针,array[3]->数组有3个元素,每个元素是int *型,即指向整形变量的指针类型printf("%d,%d,%d\n",array[0],array[1],array[2]);printf("%d,%d,%d\n",*array[0],*array[1],*array[2]);//*为取值运算符printf("%d\n",&array[0]);//(数组也有它自己的地址)printf("%d\n",array);//&array[0]=array=&arrayprintf("%d\n",&array);//&array[0]=array=&array//	int *p=array;××因为array是int *型的,所以我们要定义int *型的指针,才能指向这个数组int **p=array;//拆成3部分看容易理解,int *看作类型,*表示是int *类型的指针,p代表变量名//即指向指针的指针printf("%d,%d,%d\n",&array[0],&array[1],&array[2]);//(数组也有它自己的地址)printf("%d,%d,%d\n",p,p+1,p+2);//(通过指针拿到数组单元的地址)printf("%d,%d,%d\n",*(p+0),*(p+1),*(p+2));//(通过取值运算符*拿到数组单元的值)printf("%d,%d,%d\n",**(p+0),**(p+1),**(p+2));//(通过取值运算符*拿到数组单元的地址所指向的值)//在自己动手实验的过程中,我发现变量的内存分配好像是自顶向下,是递减规律
//而数组单元间的地址值是递增规律}

运行结果 

6684180,6684176,6684172
6684180,6684176,6684172
1,2,3
6684144
6684144
6684144
6684144,6684152,6684160
6684144,6684152,6684160
6684180,6684176,6684172
1,2,3

二维数组续

 

#include <stdio.h>
int main()
{int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};int *p0=a[0];//第一层首元地址int *p1=a[1];//第二层首元地址int *p2=a[2];//第三层首元地址printf("*p0=%d\n",*p0);printf("*p1=%d\n",*p1);printf("*p2=%d\n",*p2);printf("*a[0]=%d\n",*a[0]);printf("*a[1]=%d\n",*a[1]);printf("*a[2]=%d\n",*a[2]);int (*p)[4]=a;//p指向int[4],即指向4个int类型的连续空间,4*4=16Byteprintf("a[0]=%d\n",a[0]);printf("a[1]=%d\n",a[1]);printf("a[2]=%d\n",a[2]);printf("\n");printf("p0=%d\n",p0);printf("p1=%d\n",p1);printf("p2=%d\n",p2);printf("\n");printf("p+0=%d\n",p+0);//二维数组第一层printf("p+1=%d\n",p+1);//+1不是简单的加1,而是加到下一个16Byte的空间  第二层printf("p+2=%d\n",p+2);//二维数组第三层printf("\n");printf("*(*(p+0)+0)=%d\n",*(*(p+0)+0));printf("*(*(p+0)+0)=%d\n",*(*(p+1)+0));printf("*(*(p+0)+0)=%d\n",*(*(p+2)+0));printf("\n");//	因此遍历二维数组就有了两种方式
//	方式一for(int i=0;i<3;i++){	//最外层控制行for(int j=0;j<4;j++){	//内层控制列printf("%d ",a[i][j]);}printf("\n");}printf("\n");
//	方式二for(int i=0;i<3;i++){	//最外层控制行for(int j=0;j<4;j++){	//内层控制列printf("%d ",*(*(p+i)+j));}printf("\n");}
//	总结:c语言里的二维数组是连续空间,所以可以进行上述操作return 0;
}

运行 

*a[0]=0
*a[1]=4
*a[2]=8
a[0]=6684096
a[1]=6684112
a[2]=6684128p0=6684096
p1=6684112
p2=6684128p+0=6684096
p+1=6684112
p+2=6684128*(*(p+0)+0)=0
*(*(p+0)+0)=4
*(*(p+0)+0)=80 1 2 3
4 5 6 7
8 9 10 110 1 2 3
4 5 6 7
8 9 10 11

指针+字符串

#include <stdio.h>
int main()
{	//好好学习,天天向上。char *str1="好好学";char *str2="习,天";char *str3="天向上";char *str[3]={str1,str2,str3};printf("%s%s%s",str[0],str[1],str[2]);;return 0;
}

运行结果

好好学习,天天向上

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#使用MiniExcel读取excel表格文件

使用MiniExcel读取excel表格文件 MiniExecl提供了几种读取方法。 准备测试数据 测试类&#xff1a; public class Person{public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }public double Value { get; set; }}测试数据…

QT信号与槽实现方式

1、第一种实现方式 在QT开发工具UI界面先拖入按钮&#xff0c;然后鼠标右键拖入按钮&#xff0c;点击选中槽&#xff0c;在页面选着需要的信号&#xff0c;然后OK&#xff0c;随即将会跳转到类的.cpp文件&#xff0c;&#xff08;这种UI代码结合的方式&#xff0c;会自动去绑定…

什么是分段锁?

1、典型回答 分段锁是一种将锁细化到每个段(Segment) 级别的锁设计。在 ConcurrentHashMap 中&#xff0c;它将整个数据结构分成多个段&#xff0c;每个段只锁定自己的一部分数据。每个段可以看作是一个独立的分组&#xff0c;只锁定该段(Segment)内部的数据操作&#xff0c;不…

springboot271制造装备物联及生产管理ERP系统

制造装备物联及生产管理ERP系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装制造装备物联及…

Mysql 无法启动,mysql-bin.日志丢失删除处理

在linux操作系统中&#xff0c;当mysql无法启动时候&#xff0c;先看日志 2024-03-15T05:20:16.352075Z 0 [Warning] [MY-000081] [Server] option max_allowed_packet: unsigned value 107374182400 adjusted to 1073741824. 2024-03-15T05:20:16.352156Z 0 [Warning] [MY-010…

【数据结构和算法初阶(C语言)】栈的概念和实现(后进先出---后来者居上的神奇线性结构带来的惊喜体验)

目录 1.栈 1.1栈的概念及结构 2.栈的实现 3.栈结构对数据的处理方式 3.1对栈进行初始化 3.2 从栈顶添加元素 3.3 打印栈元素 3.4移除栈顶元素 3.5获取栈顶元素 3.6获取栈中的有效个数 3.7 判断链表是否为空 3.9 销毁栈空间 4.结语及整个源码 1.栈 1.1栈的概念及结构 栈&am…

手撸dynamic源码详细讲解

本文源码解析基于3.3.1版本。只截了重点代码&#xff0c;如果需要看完整代码&#xff0c;可以去github拉取。 1 自动配置的实现 一般情况下&#xff0c;一个starter的最好入手点就是自动配置类&#xff0c;在 META-INF/spring.factories文件中指定自动配置类入口 org.spring…

QTextToSpeech的使用——Qt

前言 之前随便看了几眼QTextToSpeech的帮助就封装使用了&#xff0c;达到了效果就没再管了&#xff0c;最近需要在上面加功能&#xff08;变换语速&#xff09;&#xff0c;就写了个小Demo后&#xff0c;发现不对劲了。 出现的问题 场景 写了个队列添加到语音播放子线程中&a…

Jenkins cron定时构建触发器

from&#xff1a; https://www.jenkins.io/doc/book/pipeline/syntax/#cron-syntax 以下内容为根据Jenkins官方文档cron表达式部分翻译过来&#xff0c;使用机翻加个人理解补充内容&#xff0c;包括举例。 目录 介绍举例&#xff1a;设置方法方法一&#xff1a;方法二&#xf…

UG NX二次开发(C#)-单选对话框UF_UI_select_with_single_dialog的使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、UF_UI_select_with_single_dialog函数3、实现代码3.1 利用委托创建一个方法3.2 直接调用1、前言 对于单选对话框,采用C++/C写的时候比较容易,也在帮助文档中有示例,但是对于C#开发采…

C# StartsWith 字符串的实例方法

在 C# 中&#xff0c;StartsWith 是一个字符串的实例方法&#xff0c;用于检查字符串是否以指定的前缀开头。它返回一个布尔值&#xff0c;指示字符串是否以指定的前缀开始。 以下是 StartsWith 方法的详细解释和示例说明&#xff1a; public bool StartsWith(string value);…

EtherCAT运动控制器在ROS上的应用(下)

本篇文章我们主要介绍正运动技术动态链接库环境配置以及EtherCAT运动控制器在ROS下的单轴运动。 在正式学习之前&#xff0c;我们先了解一下正运动技术的EtherCAT运动控制器ZMC432和ZMC408CE。这两款产品分别是32轴&#xff0c;8轴EtherCAT运动控制器。 ZMC432功能简介 ZMC4…