关于二维数组和二级指针的理解
可以参考《C语言专家编程》的第10章
一、首先指针和数组有着密不可分的联系,指针变量可以当做数组来用,在用之前,应该先让指针指向一个数据块, 这个数据块
①可以是程序中的某一个变量,
int a;
int *p = &a
或
int a;
int *p;
p = &a;
②也可以是某一个数组,
int a[3];
int *p = a;//此时a就是地址
或
int a[3];
int *p;
p = a;
③还可以是一个新开辟的内存空间
int *p;
p = (int *)malloc(sizeof(int));
其实一级指针没有什么好说的,但是级数越高程序就越不好理解。
二、接下来就是二级指针和二维数组的传递关系
若char **p, a[3][2];
是否p = a;
以前我一直认为a[]是一级指针,a[][]就是二级指针,到底还是自己写程序太少。
接下来就用程序说话
#include <stdio.h>
#include <stdlib.h>
void tmp(int **aa)
{
aa[0][0] = 10;
}
int main()
{
int aa[3][2] = { 0 };
tmp(aa);
printf("%d\n", aa[0][0]);
system("pause");
return 0;
}
在GCC上编译后出现
error: cannot convert 'int (*)[2]' to 'int**' for argument '1' to 'void tmp(int**)'
于是在翻阅网上的各种资料后发现《C语言专家编程》10.5节上有了明确的答案,
比较正常的传递多维数组的方法有3中(还有一种太复杂,想了解的可以看书)
①
my_function(int my_array[10][20]);
②
my_function(int my_array[][20]);
或
my_function(int (*my_array)[20]);//数组指针
③
my_function(int **my_array);
数组和指针参数是如何被编辑器修改的:
"数组名被改写成一个指针参数"规则并不是递归定义的。数组的数组会被改写“成数组的指针”,而不是“指针的指针”
[]的优先级高于*
实参
所匹配的形参
数组的数组
char c[8][10];
char(*c)[10] 数组指针
指针数组
char *c[15];
char **c;
指针的指针
数组指针(行指针) char (*c)[64];
char (*c)[64]; 不改变
指针的指针
char **c;
char **c;
不改变
#include <stdio.h>
#include <stdlib.h>
void tmp(int (*aa)[2])//二维数组变成了数组指针
{
for(int i = 0; i < 6; i++)
for(int j = 0; j < 2; j++)
aa[i][j] = i + j + 10;
}
int main()
{
int aa[3][2] = { {1, 2}, {3, 4}, {5, 6} };
tmp(aa);
for(int i = 0; i < 3; i++)
for(int j = 0; j < 2; j++)
printf("aa[%d][%d] = %d\n", i, j, aa[i][j]);
system("pause");
return 0;
}
还有一个也是我经常使用的,但是它不是二维数组与指针之间的转化,而是用到了 数组的内存是线性连续的
#include <stdio.h>
#include <stdlib.h>
void tmp(int aa[])
{
for(int i = 0; i < 6; i++)
aa[i] = i;
}
int main()
{
int aa[3][2] = { 0 };
tmp(*aa);//将aa[3]的地址传入
for(int i = 0; i <3; i++)
for(int j = 0; j < 2; j++)
printf("aa[%d][%d] = %d\n", i, j, aa[i][j]);
system("pause");
return 0;
}
通过VS的调试工具
可以看到虽然aa[3][2]的初始化都为0,但是当调用tmp(aa);子函数值还是被改变了,所以可以看到数组的内存是连续的