关乎指针好像问题层出不穷,到了二叉树的时候小编才发现问题真的是多的不得了,所以赶忙回去重新看了下指针。
指针数组问题
首先来看下面一段代码
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", &arr);
这里面发现打印出来的地址是一样的,但是真的是所有的都完全一样吗?并非如此,打开监视窗口调试一下就可以看到arr类型是int[10],其后值的类型是int 类型,但是&arr的类型是int*[10];其后值的类型也是int,但是对arr 和 &arr进行操作的时候就会大不相同
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
这时候就会出现arr+1只是将指针后移了一个int所占字节,而&arr+1却将指针向后移动了一个数组。这时候强调2点
- 指针加1
指针加一跳过其指向类型的字节 - 数组名称是指针 是指向数组首元素的指针
数组名称的类型是将数组名称去掉后所剩余的类型。 - 二维数组传参,函数形参的设计只能省略第一个[]的数字,因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素,这样才方便运算。我们重点来看二维数组传参数应该怎么传
传参分为传值和传地址,首先来看我们能将二维数组所有的值传递到函数当中去吗?
例如这样
int arr[2][3] = { 1,2,3,4,5,6 };
//编写函数将为二维数组打印出来
print(arr[2][3], 2, 3);
如果你这么写代码那真的是对于指针数组基本上是一窍不通,你这样写传递的是一个常量,打开监视窗口传递的是二维数组第3行第4个元素,已经越界。我们传数组和传结构体等含有多个值的时候不会用一个值一个值传递,而是传递一个地址,听过这个地址可以找到数组或者结构体。因此在实际参数中应该是传数组地址
int arr[2][3] = { 1,2,3,4,5,6 };
//编写函数将为二维数组打印出来
print(arr, 2, 3);
接下来看这个函数的实现
void print(int arr[2][3], int col, int row)
{
int i = 0;
int j = 0;
for ( i = 0; i < col; i++)
{
for ( j = 0; j < row; j++)
{
printf("%d ", arr[i][j]);
}
}
}
在形参中定义a[2][3]来存放这个数组完全可以。
再看一种方式
void print(int (*arr)[3], int col, int row)
{
int i = 0;
int j = 0;
for ( i = 0; i < col; i++)
{
for ( j = 0; j < row; j++)
{
printf("%d ", *(*(arr+i)+j));
}
}
}
这就是我们强调的数组指针所用之地
- 函数指针
函数名称是函数的地址
函数名和&函数名都是函数的地址
来看
void test(void)
{
printf("hehe");
printf("\n");
}
int main()
{
test();
(*test)();
system("pause");
return 0;
}
打印的结果是一样的。
我们就来看这个*加不加好像都一样,再来证实一下
(*******test)();
打印结果还是一样,所以这个*只是为了帮助理解语法,完全就是摆设。
想用个指针指向函数应该怎么去指向?
int test(int x,int y)
{
return x + y;
}
想要用个指针指向这个函数应该怎么执行?
int(*p)(int, int) = test;
这时候指针p就是指向这个函数的指针,
printf("%d ", (*p)(1, 2));
printf("%d ", p(1, 2));
同样这个*也是个摆设。