数组名代表整个数组的两种情况:sizeof(数组名) &(数组名);其他出现数组名的情况表示首元素的地址;
1.指针数组:指针数组是数组,是一个存放指针的数组。
例子:
Int *arr1[10]; //arr1里面存放int *变量
char *arr2[4]; //arr2里面存放char *变量
char **arr2[5]; //arr3里面存放char **变量
整型数组存放整型变量;float型数组存放float型变量;
2.数组指针:数组指针是指针。
例子:
int (*p)[10];
整型指针表示指向整型的指针; 整型指针加1实际上是加4
char型指针表示指向char型的指针; char型指针加1实际上是加4
double型指针表示指向double型的指针; double型指针加1实际上是加8
数组指针表示指向数组的指针; 数组指针加1实际上是加上整个数组;
结论:(1)指针加1,实际上是加上其所指向类型的大小;
(2)[]优先级高于*;
(3)数组的地址和数组首元素的地址数值相等,但意义不同;
(4)如果两个变量的类型相同,则它们开辟的空间大小也相同;
如果两个变量开辟的空间大小相同,则它们的类型不一定相同;
(5)数组的大小也是决定数组类型的一个重要指标;
数组传参时会降维成指向其内部元素类型的指针(降维是为了节省性能和空间方面的开销);整型一维数组降维成整型指针;三维数组降维成指向二维数组的指针。
所有数组都是一维数组,(一维/多维)数组在内存中存储的方式是线性存储;
多维数组传参时,只有第一个方括号里的数字可以省略(因为对于一个二维数组,可以不知道有多少行,但必须知道一行有多少元素,这样才方便运算)。
3.函数指针
printf(“%p\n”, test); //函数的名称(test)是函数的地址
printf(“%p\n”, &test); //test和&test相同
函数指针是变量,里面放的是指针;
函数的入口地址是函数名(&函数名);
函数地址即函数指针;
函数指针变量保存函数的地址;
void (*pfun1)(); //函数指针
void *pfun2(); //函数的声明
4.函数指针数组
把函数的地址存到一个数组中,这个数组叫函数指针数组;
int (*parr1[10])(); //函数指针数组的定义
函数指针数组的用途:转移表
5.指向函数指针数组的指针
指向函数指针数组的指针是一个指针,指针指向一个数组,数组的元素都是函数指针;
void (*pfun)(const char*)=test; //函数指针,指向test
void (*pfunArr[5])(const char* str); //函数指针数组的指针
pfunArr[0]=test;
void (*(*ppfunArr)[10])(const char*)=&pfunArr; //函数指针数组的指针变量
6.指针和数组都是一种类型,但是两者本质上是不同的。
7.C语言中,(数组/指针)函数传参时一定会形成临时变量:
(1)指针传参时形成的临时变量和指针变量不同,但两者指向的内容是相同的;指针传参是传址传参,所传地址可以使变量访问指针所指向的内存空间。
(2)数组传参时会降维成指向其内部元素类型的指针(降维是为了节省性能和空间方面的开销);所有数组都是一维数组;整型一维数组降维成整型指针;三维数组降维成指向二维数组的指针。