IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言二维数组和指针数组-笔记(十一) -> 正文阅读

[C++知识库]C语言二维数组和指针数组-笔记(十一)

一、指向一维数组的指针常用运算

已知:一维数组:a[i]={0,1,2,3,4,…,i};*p=a;
在这里插入图片描述

故:a[i]=*(a+i)=p[i]=*(p+i)=*p++

二、二维数组中的行地址和列地址

1、列地址

(1)定义:第几个元素的地址,用单下标或双下标+&或*+行地址表示列地址。

如:a[0] 、a[i]&a[0][0]*a、*(a+i)

已知:int a [3][4]={{0,1,2,3},{4,5,6,7},{8, 9,10,11}};
可把二维数组a 看成三个一维数组组成, 即a[0]、a[1]、a[2],它们是这三个一维数组的首元素的地址,也是这个二维数组的列地址。
在这里插入图片描述
列地址+1 或 列地址-1 表示左移或右移一个数据元素。
二维数组中:a[i]==*(a+i),表示数组a中第i行第0个元素的列地址。
a[0]、a[1]、a[2]是一维数组名,数组名代表数组首元素地址,故a[0]代表一维数组a[0]中第0列元素地址,即&a[0][0],a[1]值则为&a[1][0],a[2]值则为&a[2][0]
数组a中第i行第j列元素地址:
在这里插入图片描述

00列元素地址: a[0]+0 == *(a+0)+0 == &a[0][0] == 2000==a[0]==*(a+0)==*a
第01列元素地址: a[0]+1 == *(a+0)+1 == &a[0][1] == 200410列元素地址: a[1]+0 == *(a+1)+0 == &a[1][0] == 2016==a[1]==*(a+1)12列元素地址: a[1]+2 == *(a+1)+2 == &a[1][2] == 202420列元素地址: a[2]+0 == *(a+2)+0 == &a[2][0] == 2032==a[2]==*(a+2)
*(a+i)表示第i行第0个元素的列地址
*(a+i)+j 表示第i行第j个元素的地址(=&a[i][j])

在一维数组中,a[i]表示a数组中序号为i的元素存储单元具有物理地址,占据存储空间。
在多维数组中,a[i]是一维数组名,只是一个地址,不代表某一个元素的值。

&a[i][j]=a[i]+j=a[0]+j=*(a+i)+j。

(2)列地址使用
使用列地址时,是将整个二维数组看成同一行。

#include <stdio.h>

int main()
{
   int a[3][3]={1,2,3,4,5,6,7,8,9};
   int i;
   for (i=0;i<9;i++)       	
	 {
		printf("%d",*(a[0]+i));//输出:123456789
	 }
   printf("\na[1][2]=%d",a[1][2]);//输出:a[1][2]=6
   printf("\na[1][2]=%d",*(a[0]+5));//输出:a[1][2]=6
   printf("\na[1][2]=%d",*(a[1]+2));//输出:a[1][2]=6
   printf("\n");
   return 0;
}

结论:按列地址输出,可采用以上不同方式输出,效果一致。
列地址使用列指针来指向(指向数组元素的指针),赋值方法是:
p=a[0]、p=&a[0][0]、p=*a

2、行地址

(1)定义:数组中的第几行,用不带下标的数组名或&+列地址表示。
如: a、a+i(不带下标的数组名)。(a+1:表示下移一行)

 &a[2]=&*(a+2)=a+2  (*&有抵消作用)

已知:int a [3][4]={{0,1,2,3},{4,5,6,7},{8, 9,10,11}};
在这里插入图片描述
从二维数组角度看,a代表二维数组首元素地址,此时首元素不是一个简单的整型元素,而是由4个整型元素组成的一维数组,故a为首行行地址(a=2000),
则a+1=2000+44=2016。
由于a[0]与
(a+0)即*a等价,所以&a[0]就与&*a等价。而&*a就是a,它是行地址。

故:a+i=&a[0]=&*(a+i)

(2)行地址使用
使用行地址时,是将整个二维数组看成i行j列。
如:
a 表示第0行的行地址 == &a[0]
a+1 表示1行行地址
a+i 表示第i行的行地址

注:行地址使用行指针来指向(指向一维数组的指针)

三、二维数组中的行指针和列指针

1、元素

(1)*+列地址=元素

*&a[i][j]=a[i][j]=*(a[i]+j)=*(a[0]+j)=*(*(a+i)+j)
如:
a[0][0]相当于**(a+0)+0)
a[1][2]相当于**(a+1)+2*(a+i)+j 表示第i行第j个元素的列地址(=&a[i][j])

(2)**+行地址=元素 (行地址本质上是二级地址,通过它取元素值时要多加一次*运算)

如:
**a       表示第00列元素值(=a[0][0])*(*(a+i))   表示第i行第0列元素值(=a[i][0]);1行第2列元素值: *(a[1]+2) == *(*(a+1)+2 )== a[1][2]。
故 *(*(a+i))=*(*(&a[0]))=*(*(&*(a+i)))

2、列指针(赋予列地址)

(1)定义
列指针:指向数组元素的指针变量。

如:int *p;
p=&a[0][0]或p=a[0]或p=*a;

则用p表示每个数组元素地址,方法为:p+i,表示距离a[0][0]第i个位置的元素的地址。
(2)应用
例1:

#include <stdio.h>

int main()
{
	int a[3][3]={1,2,3,4,5,6,7,8,9};
	int *p,*q;
	system("cls");
	p=&a[0][0];/* p=a[0],p=*a也可以 */
	q=&a[2][2];
	for (;p<=q;p++)
	{
		printf("%d ",*p);
	}
	printf("\n");
	return 0;
}
//执行输出:1 2 3 4 5 6 7 8 9

例2:

#include <stdio.h>

int main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
   int *p;
	//p=a;
	//p=&a[0][0];
   p=a[0]; 
   for (;p<a[0]+9;p++)       	
	{
	  printf("%x,%d\n",p,*p); //输出地址和元素值
	}   
return 0;
}

3、行指针(赋予行地址)

(1)定义
行指针:指向有m个元素组成的一维数组的指针变量。

格式:int (*p)[n];p=a;

含义:定义p是指向含有n个整形数据元素的一维数组的指针变量。即行指针。

如:int (*p)[4];
    int a[3][4];
    p=a;

p=a实现指向操作。行指针p是行地址性质的指针。此时,p+i=a+i,指向第 i行行首。
p+i表示第i行元素的地址等价于a+i;可以与二维数组用数组名表示的行地址互换使用。
在这里插入图片描述

p+i表示数组a的第i行的行地址。
*(p+i)相当于a[i],是指向第i行第0列的列地址。如*(p+2)相当于a[2]*(p+i)+j相当于a数组第i行第j列的列地址,如*(p+2)+1相当于&a[2][1]
a[2][1] == *(*(p+2)+1)
故当p是行指针时共有下面四种方法表达a[i][j]:
p[i][j]= * (*(p+ i)+j)= (*(p+ i))[j]= *(p[i]+j)=a[i][j];

例1:

#include <stdio.h>

int main()
{
   int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
   int (*p)[4],i,j;
   p=a;
   scanf("%d%d",&i,&j);
   printf("a[%d][%d]=%d\n",i,j,*(*(p+i)+j)); 
   return 0;
}
//执行输出:1 2
// a[1][2]=13

例2:

#include <stdio.h>

int main()
{
    int a[3][3]={1,2,3,4,5,6,7,8,9};
	int (*p)[3];
	int i,j;
	p=a;
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			//printf("a[%d][%d]=%d\n",i,j,a[i][j]);
			//printf("a[%d][%d]=%d\n",i,j,p[i][j]);
			//printf("a[%d][%d]=%d\n",i,j,*(p[i]+j));
			//printf("a[%d][%d]=%d\n",i,j,*(*(p+i)+j));
			printf("a[%d][%d]=%d\n",i,j,(*(p+i))[j]);			
		} 
	}
	printf("\n");
	return 0;
}
//执行输出:1 2 3 4 5 6 7 8 9

四、指针数组

1、概念

一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。
格式:类型名数组名[数组长度];
例如:
int *p[4]; p是一个具有4个元素的数组,每个元素都是一个能指向int型数据的指针变量。
注意:和 int (*p)[4]区别:p是一个指针变量,它能够指向一个具有4个元素的一维数组,也称数组指针。

2、指针数组应用

例:

#include <stdio.h>

int main()
{
	char*weeks[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
	int i;
	do
	{	
		scanf("%d",&i);
	}while(i<0||i>6);	
	printf("%s\n",weeks[i]);	
	return 0;
}
//执行输出:1
//Monday

3、数组指针(行指针)和指针数组的比较

(1)指针指向二维数组:数组指针(行指针)

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i=0,j=0;
	int a[3][3]={1,2,3,4,5,6,7,8,9};
	int (*p)[3]=a;//数组指针(行指针),3个指针相当于3*3二维数组
	//一行是一个一维数组,3*3二维数组则是3个一维数组
	//()优先级最高,p为一维指针,指向整型一维数组,数组长为3
	printf("地址:%p\n",a);//数组首地址-->地址:0019FF1C
	printf("地址:%p\n",a[0]);//第一个一维数组起始地址-->地址:0019FF1C
	printf("地址:%p\n",&a[0]);//数组起始地址-->地址:0019FF1C
	printf("地址:%p\n",&a[0][0]);//数组首元素地址-->地址:0019FF1C
	
	printf("地址:%p\n",a[1]);//第二个一维数组起始地址-->地址:0019FF28
	printf("地址:%p\n",&a[1]);//同上 相差&a[0] 12B
	printf("地址:%p\n",&a[1][0]);
	//第二个一维数组首元素地址-->地址:0019FF28
	
	for(i=0;i<3;i++)//指针与二维数组应用,输出数组元素值
	{
		for(j=0;j<3;j++)
		{
			printf("%d",*(*(p+i)+j));//123456789
			//p为地址->(p+i)为地址行偏移->*(p+i)->取值为行地址->*(p+i)+j->
			//加该行上列地址偏移,生成总地址->*(*(p+i)+j)->对总地址取*,即该地址所指变量
			//printf("%d",*(p[i]+j));//123456789
			//printf("%d",*(&p[0][0]+i*3+j));//123456789
			// printf("%d",(*(p+i))[j]);//123456789
		}
	}
	printf("\n");
	return 0;
}

(2)指针数组

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i=0;
	char *name[3]={"admin","user","reader"};//定义并初始化指针数组
	for(i=0;i<3;i++)
	{
	   printf("%s\n",name[i]);//按下标法进行访问
	}
	//admin
	//user
	//reader
	return 0;
}
//指针数组:数组里存放指针变量,它本身就是数组

比较:
int *s1[3], 则s1是具有三个整型指针元素的数组
(*s2)[3] , 则s2是指向具有三个元素的整型数组的指针

编辑 2020-07-03 23:58 首次编辑
增改 2021-07-10 18:27 内容结构优化

注:本文旨于作为自己的学习笔记,不作他用。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:27:42  更:2021-07-11 16:28:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 20:43:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码