C:指针与数组总结·下【字符指针,数组指针,函数指针,函数指针数组】
在上一篇里已经讲过什么是指针了,也提及了数组与指针,这里主要梳理总结指针的高级主题。
字符指针
char*
是指针的一种类型,叫做字符指针。
举个栗子:
//(1)
int main()
{
char com = 'w';
char* p = &com;//*p = w
return 0;
}
//(2)
int main()
{
char* p = "hello";
printf("%s\n",p);
return 0;
}
上面两个p都是字符指针,现在我们已经知道字符指针是什么了。对比一下两个程序,你觉得(2)中p里存放的是什么?答:p中放的是字符串"hello"
的的首地址,也就是h
的地址,指针p指向的是h
。
数组指针
记住上面的存储方式,接下来我们引入数组指针的概念。
上一篇博客中讲过指针数组的概念,这里不再赘述,数组指针是指针,存放的是数组的地址,注意数组的地址和数组首元素地址是不同的概念,举个栗子:
int arr[10] = { 0 };
printf(“%p\n”,arr);
printf("%p\n",&arr);
运行结果:
打印出来看到两个地址是相同的,呢是不是就说明&arr
就是首元素地址呢,不是的,我们再来举个栗子:
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int *p = arr + 1;
int (*b)[10] = &arr + 1;
printf(“%p\n”,p);
printf("%p\n",&arr[1]);
printf("%p\n",b);
运行结果:
现在是什么情况就一目了然了,指针加1是使指针指向下一个地址的内容,如果&arr
是首元素地址,呢b+1
就指向1的位置,应该和&arr[1]
地址相同,但是看运行结果,与首元素地址相差40个字节,说明&arr
是数组的地址,数组的地址加1就跳过这个数组指向数组后面的那块空间了。
看上面的代码应该能发现既然数组指针存的是数组的地址,而
&arr
就是数组的地址,呢b就是一个数组指针
int (*b)[10]
的意义:b和*结合表示b是一个指针,这个指针指向的是一个有10个元素且为整型的数组。//[]
的优先级要高于*
,注意要加()
。
从上面应该能看出
&数组名
和数组名
是不同的,总结一下:
1.arr是数组名,数组名是首元素地址
2.&arr
是数组的地址
3.数组的地址加1,跳过整个数组
4.首元素地址加1,跳过第一个元素
数组的地址在二维数组中使用感比较强,一维数组不太明显,这里不多讲解,直接总结:
1.二维数组的数组名表示首元素地址
2.二维数组的首元素是第一行的元素
3.所以二维数组是数组名其实是第一行一维数组的地址
4.接收二维数组的数组名相当与接收第一行一维数组的地址,数组的地址要用数组指针接收。
5.当需要数组传参时,定义函数参数时接收二维数组首元素地址要用一个数组指针来接收,这就是数组指针的应用。
函数指针
简单介绍一下:
void(*p)();
这是一个函数指针,p与*先结合,是一个指针变量,去掉*p
剩下的void()();
是p的类型,说明p指向的是一个无参数无返回值的函数。- 函数指针:指向函数的指针;
- 函数的
函数名
就是函数的地址; &函数名
也是函数的地址;
这里注意和数组区分!!
函数指针数组
这里是一个比较绕的概念,如果之前的东西你都分清楚了,呢类比一下也能弄懂这个。
1.从字面意思解释,函数指针数组是一个数组
2.数组里存放的是指针
3.指针里放的是函数的地址
4.所以指针是函数指针
5.总结下来就是函数指针数组。
写法也同上面差不多:
1.因为是个数组:–>p[10]
说明p是个数组,有10个元素
2.数组的类型:–>p是存放函数指针的数组,所以p的类型就是函数指针类型–>int (*)(int ,int);这表示这个函数指针指向的是一个参数是(整型,整型),返回值是整型的函数。
3.int (*p[10])(int,int);------函数指针数组