指针的详解:
1.字符指针
2.数组指针
3.指针数组
4.数组传参和指针传参
5.函数指针
6.函数指针数组
7.指向函数指针数组的指针
8.回调函数
9.指针和数组面试题的解析
正文开始:
指针的概念:
1.指针就是个变量,用来存放地址,地址唯一标识一块空间。
2.指针的大小是固定的4/8个字节(32位平台/64平台)
3.指针是有类型,指针的类型决定了指针的+-步长指针解引用操作时候的权限
4.指针的运算
字符指针:
//int main()
//{
// char arr[] = "abcde";
// char* ch = &arr;
// printf("%s", arr);
// printf("%s", ch);//这里字符串会根据这个地址一直向后找直到招到\0
// return 0;
//}
判断下面代码打印出来是hehe还是haha
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
char* p1 = "abcdef";
char* p2 = "abcdef";
if (arr1 == arr2)//由于arr1与arr2指向的是首元素地址,是不一样的。所以打印haha
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
第二种
if (p1 == p2)//这里abcdef是常量字符串不能被修改所以p1和p2的地址是一样的打印hehe
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
}
指针数组
在初识指针里我们学习了指针数组,指针数组是一个存放指针的数组;
下面指针数组是什么意思?
int main()
{
int arr[10] = { 0 };//整形数组;
char ch[5] = { 0 };//字符数组;
int* parr[4];//存放整形指针的数组-指针数组;
char* pch[5];//存放字符指针的数组-字符数组;
return 0;
}
那么我们怎么去用它呢?
举个例子:
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
int* parr[] = { arr1, arr2, arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", *(parr[i] + j));
}
printf("\n");
}
}
数组指针
数组指针的定义:
数组指针是数组还是指针? 是指针
我们已经熟悉整形指针int*pint:能够指向整形数据的指针,浮点型指针:float*pf;能够指向浮点型数据的指针。
那么数组指针应该是:能够指向数组的指针;
下面哪个代码是数组指针?
int main()
{
//int* p = NULL;//P是整形指针,-指向整形的指针-可以存放整形的地址;
//char* pc = NULL;//pc是字符指针-指向字符的指针-可以存放字符的地址;
//数组指针-指向数组的指针-存放数组的地址
int arr[10] = { 0 };
//arr-首元素地址
//&arr[0]-首元素的地址
//&arr-数组的地址
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//数组的地址要存放起来;加上()的原因是[]的优先级比*高;
//上面的p就是数组指针
return 0;
}
//举个例子
int main()
{
char* arr[5];
char* (*pa)[5] = &arr;
//pa是指针变量的名字,*说明pa是指针;[]说明pa指向的数组是5个元素的;char*说明pa指向的5个数组的元素类型是char*;
return 0;
}
数组名VS&数组名
对于下面数组;
int arr[10] = {0};
arr 和&arr分别是啥?
我们知道arr是数组名,数组名表示数组首元素的地址。
那么&arr数组名到底是啥?
//数组指针一般在二维数组及以上会用到;举个例子
void print1(int arr[3][5], int x, int y)
{
int i = 0;
int j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print2(int(*p)[5], int x, int y)
{
int i = 0;
for (i = 0; i < x; i++)
{
int j = 0;
for (j = 0; j < y; j++)
{
//printf("%d ", *(*(p + i) + j));//这里p+i是二维数组中每一行的地址,解引用它得到它的地址,再加上j得到每个元素的地址;
//*(p + i) + j是指向第i行第j列的地址, * ( * (p + i) + j)是指向第i行第j列的元素值。
printf("%d ", (*(p + i))[j]);//也可以这样写;//不理解请看下面代码;
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };//这里arr是数组名。数组名就是首元素地址,那么在二维数组中,数组名就是第一行的地址
print1(arr, 3, 5);
print2(arr, 3, 5);
}
//}printf("%d ", (*(p + i))[j]);这里不理解请看下面代码
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int* p = arr;
for (i = 0; i < 10; i++)
{
printf("%d ", p[i]);//这里arr[i] == *(arr+i) == *(p+i) == p[i];
}
return 0;
}
对下面类型做解释:
int arr[5]; //arr是一个5个元素的整形数组;
int *parr1[10]; //parr1是一个数组,数组有10个元素;每个元素的类型是int*;parr1是指针数组;
int (*parr2)[10]; //parr2是一个指针,该指针指向了一个数组,数组有10个元素,每个元素的类型是int;parr2是数组指针;
int(*parr3[10])[5]; //parr3是一个数组,该数组有10个元素,每个元素是一个数组指针,该数组指针指向的数组有5个元素,每个元素是int