1.指针与数组没有关系!
指针在32位系统下永远只占4个字节,存储着一个地址。它可以指向任何地方,但不一定能够通过指针访问到。
数组的大小和他的元素类型与数量多少有关,可以存储任何类型的元素(除了函数)。
2.以指针的方式访问和以下标的方式访问。
<1.访问指针
char* p = "abcdefg";
char receive1;
char receive2;
receive1 = *(p + 4);
receive2 = p[4];
vs2013实验结果如下
两种写法都可以达到访问目的。
<2.访问数组
char p[] = "abcdefg";
char receive1;
char receive2;
receive1 = *(p + 4);
receive2 = p[4];
vs2013实验结果如下
同样的,两种写法都可以达到访问目的。
3.数组名的意义。
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素的地址。
下面看一个例子:
int a[5] = { 1, 2, 3, 4, 5 };
int*ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
&a为整个数组地址
&a+1则应加上整个数组大小,为下一个数组的地址(即指向5的后面一个元素的位置)。
*(a+1)中a则是数组首元素的地址。
结果易得为 2 ,5。
4.指针数组与数组指针
指针数组是 数组! 数组的元素是指针
数组指针是 指针! 指针指向的是数组
举个栗子!
int *p1[10];
int(*p2)[10];
“[]”的优先级比“*”要高
故p1先与[10]结合,它首先是一个数组,元素个数为10,元素类型为int *。
p2先与*结合,它首先是一个指针,指向一个元素个数为10的数组,元素类型为int。
5.二维数组
二维数组可看成元素类型为数组的一维数组。
那么多维呢?
n维数组可看为元素为n-1维数组的一维数组。
至此,所有数组都可看成一维数组。
举个栗子!
char a[3][4];
a先与[3]结合,他是一个元素个数为3的数组,元素类型为char[4](一个元素个数为4的数组,而它的元素类型为char)
6.二级指针
char **p;
p 是一个指针变量,它与一级指针不同的是,一级指针保存的是数据的地址,二级指针保存的是一级指针的地址。
7.一维数组传参
当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。
无论你是这样写
void fun(char *p)
{
char c = p[3];//或者是 char c = *(p+3);
}
还是这样写
void fun(char a[10])
{
char c = a[3];
}
还是这样写
void fun(char a[])
{
char c = a[3];
}
传向函数的都只是数组首元素的地址,并非传过去了整个数组。
并且传参是对实参做一份 拷贝并传递给被调用的函数。即对 参数p 做一份拷贝,假设其拷贝名为_p。那传递到函数内部的就是_p 而并非 p 本身。
8.二维数组传参
最直观的的写法
void fun(char a[3][4]);
现在我们将其看作一个一维数组a[3],元素类型为char [4]。
函数声明便可改写为:
void fun(char (*a)[4]);//第二维的维数却不可省略,他确定了元素类型!
或者
void fun(char a[][4]);
当一维数组作为函数参数的时候,编译器总是把它解析 成一个指向其首元素首地址的指针。这条规则并不是递归的,也就是说只有一维数组才是 如此,当数组超过一维时,将第一维改写为指向数组首元素首地址的指针之后,后面的维再也不可改写。
9.函数指针
看一个函数指针的定义的例子
char (*p)(char p1,char p2);
如果看不懂,可以类比
char(*)[10] p;
就很容易看出这是一个指针,但它指向的是一个函数,函数的参数为(char p1,char p2)。
那么怎么通过函数指针调用函数呢?
假设函数指针 p=&fun;
如果跟其他指针一样
*p就可以调用函数,不过函数调用需要传入对应的参数
那么把参数才后面加上即可
(*p)(a, b);//a,b为char类型
10.函数指针数组
根据指针数组的定方法和指针数组的定义,我们就可以尝试去定义一个函数指针数组了。
只需要将char (*p)(char p1,char p2);
稍作修改
将变成char (*p[3])(char p1,char p2);
它便是一个指针数组了,数组存放的都是函数指针。
那么,我们又该怎么通过函数指针数组调用函数呢?
假设p中存储函数地址。
同样的p[0]中是一个函数指针*p[0]就是调用啦。
然后因为我们调用需要参数,完整调用方式则是
(*p[0])(a,b);
11.指向函数指针数组的指针
让我们再来尝试下定义这个拗口的指针
首先它说到天边还是个指针,
char*p
不过它指向函数指针数组,于是我们将之前定义好的函数指针数组拿下来替换p便成了
char(*(*p[3]))(char p1,char p2);