一.指针与二维数组(以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;
}