二维数组与二维指针

时间:2024-03-30 09:42:26

一.指针与二维数组(以martix[3][4]为例):

1.二维数组的本质:int martix[3][4]

int martix[3][4] => int[4]  martix[3],令int[4]为type, 

type martix[3]为含有三个元素的数组,每一个元素类型为int[4],int[4]是一个拥有4个int类型元素的一维数组.

2.martix名称含义(本质:二维数组的首地址常量):

&martix[0][0]    //取二维数组第零行、第零列元素的首地址。

&martix[0][0] => &(martix[0][0]) => &(*(martix+0)[0]) => &(*martix[0]) => &(*(*(martix+0))) => &(*(*martix)) => *martix.

martix[0][0]为二维数组第零行的第零个元素,其首地址为整个二维数组的首地址.

3.int martix[3][4]的指类: 

#include <stdio.h>
int main() {
	int num;
	double array[10];
	double *p;
	double matrix[3][4];
	// double[4] arr[3], *q = arr;	// 这种写法C编译器可能不接受!
	printf("%p\n", &num);
	p = &array[0];	// <=> p = &(*(array + 0));	<=> p = &*array; 
	// <=> p = array;
	printf("p=%p array=%p &array[0]=%p\n", p, array, &array[0]);
	// 证明array就是指针,且指类与p是相同的:
	printf("p+1=%p array+1=%p\n", p+1, array+1);
	// 指针+1将移动该指针的“指类”长度;因为p的指类是double,
	// 因此,p+1应该移动8B;
	// 实验结果发现,array+1与p+1移动了相同的字节数,那么,可以说明
	// array的指类就是double。
	// matrix完全可以看成是一个一维数组的首地址常量:
	// double matrix[3][4]; => double[4] matrix[3];
	// 令double[4]为type(某种数据类型);那么,对matrix的定义可以看成:
	// type matrix[3];
	// 在这个角度看,matrix就是一个一维数组名称;根据前面对一位数组名称
	// 的讨论可知,matrix是一个指针常量,且其指类为type!
	// 更进一步可知:matrix + 1将移动sizeof(type)的长度!
	// 即,sizeof(double[4])
	return 0;
}

对于一维数组名称与其对应的同指类指针变量(根据上述代码运行结果讲解):

double array[10],  *p=array; //array、p的指类是double;

array[10] <=> p[10]成立,若数组名称arrray为实参,那么形参就必须用类似于p类型的变量与之对应,

例:fun(double*p) {p[i] <=> array[i]}

fun(array);

将上述说法扩展至一般形式:type array[N],*p = array;

type可以是任意有效数据类型,以double[4]为例:

double[4] arrary[3], double[4]*p;这种格式C编译器不接受,需要调整, 

double[4] array[3]  => double array[3][4];

double[4]*p => double (*p)[4] //这里注意,*p必须加小括号,因为[]的运算优先级高于*,会成为double *(p[4]),改变原含义。

若忽略变量名称 =>double(*)[4].

综上所述, 二维数组的类型是double(*)[4];

#include <stdio.h>
int main() {
	int num;
	double matrix[3][4];
	printf("sizeof(double[4]):%d\n", sizeof(double[4]));
	printf("matrix:%p\t&matrix[0][0]:%p\n", matrix, &matrix[0][0]);
	printf("matrix+1:%p\t&matrix[0][0]+1:%p\n", matrix + 1, &matrix[0][0]+1);
	// matrix + 1移动了32B;&matrix[0][0] + 1移动了8B;
	// 说明:指针常量matrix的值与指针表达式&matrix[0][0]的值相同;
	// 但是!这不是两个类型相同的指针,即,指类不同!
	// matrix的指类是double[4];&matrix[0][0]的指类是double!
	// C编译器在处理两个指针时,在不涉及指类操作的情况下,将一视同仁!
	// scanf("%lf", &matrix[0][0]);	// 这是给二维数组第一个元素从键盘赋值
	// scanf("%lf", matrix); // 这同样可以完成上述任务!
	// 在此时,C编译器不对指针指类进行严格检查!!!
	// scanf("%lf", *matrix); // 这样的写法将使gcc的警告消失!
	// printf("matrix[0][0]:%lf\n", matrix[0][0]);
	//上述实验证明*matrix与&matrix[0][0]类型是完全相同的!
	printf("*matrix+1:%p\t &matrix[0][0]+1:%p\n", *matrix+1, &matrix[0][0]+1);
	printf("\n&matrix:%p\t &matrix+1:%p\n", &matrix, &matrix + 1);
	scanf("%lf", &matrix); // 这样的写法将使gcc的警告消失!
	return 0;
}

4.关于*martix和&martix[3][4]:

*martix => *(martix + 0) => martix[0];

&martix[0][0] => *martix => martix[0],

&martix[1][0] => &(*(martix[1]+0)) => &(*(martix[1])) => martix[1],

&martix[2][0] => &(*(martix[2]+0)) => &(*(martix[2])) => martix[2],

综上所述:martix[i]为二维数组的行指针.

二维数组与二维指针

martix[0]的指类:

*martix,对指针产生降阶作用,martix的指类是double[4],经过降阶后指类为double,所以martix[0]的指类是double.

martix[i]+1将移动8字节。

5.关于&martix:

double martix[3][4],

*(martix + i)中:

martix + i将移动i*sizeof(double[4])个字节,实际就是移动行指针,

*具有降阶作用,*(martix+i)的指类就是double类型,即,martix[i]是指针,是下标为i行的首地址,其指类是double型。

(martix[i]+j) => *(martix[i] + j)

martix[i] + j 事实上移动了j*sizeof(double)个字节。

因为martix的类型是double(*)[4],则&martix的指类就是double(*)[4],

&martix+1移动96个字节。//根据上述条件,martix的类型就是double[3][4],则&martix+1移动sizeof(double[3][4])个字节.

二.二维数组和二维指针种类:

1.二维数组(数组的数组):

double martix[3][4];

实参:double martix[3][4], 形参:double (*)[4];

访问:一般使用martix[i][j]访问元素。

#include <stdio.h>
void su(double (*p)[4]);
void su(double (*p)[4])
{
	
	printf("%f",p[1][2]);
}
int main()
{
	double martix[3][4];
	martix[1][2] = 2;
	su(martix);
	return 0;
}

2.指针数组:

double *martix[4];

实参 double *martix[4], 形参double**martix,

访问:使用*(martix[i]+j)访问元素.

#include <stdio.h>
void su(char **p);
void su(char **p)
{
	
	printf("%c",*(p[0]+1));
}
int main()
{
	char *martix[4] = {"abcd"};
	su(martix);
	return 0;
}

3.指向指针的指针:

char **martix;

实参 char**marix, 形参char**martix;

访问: *(*(martix+i)+j).

#include <stdio.h>
void su(char **p);
void su(char **p)
{
	
	printf("%c",*(*(p+0)+1));
}
int main()
{
	char *p[4] = {"abcd","abcd"},**martix = p;
	su(martix);
	return 0;
}