理解指针、数组和函数的关系

理解指针数组、数组指针、函数指针、函数指针数组及指向函数指针数组的指针

1.指针是什么

    首先,我们先看一下几个概念:

指针---->地址

指针变量---->变量(里面存放的是地址/指针)

变量指针---->变量的地址

我们习惯于说定义一个指针,其实就是定义一个指针变量。那如何定义一个指针呢


int a = 10;//在内存中开辟一块空间,用来保存变量a
int *p  = &a;取出a的地址,将它存放在变量p中

p是一个变量,是用来存放a这块内存的地址:0x0012ff42的。

总结:指针就是变量,是用来存放地址的变量,可以将地址形象地称为指针。

我们应该理解指针是为了存放地址才出现的,地址是为了标示一块地址空间;指针让地址有地方存放,指针让内存的访问更加方便;指针在32位平台上是4个字节,在64位平台上是8个字节(内存的最小单位是字节)。

我们都知道,变量有不同的类型,那么,指针既然是变量,那它有没有类型呢?

答案是有,类型是:type+ *

char *pa = NULL;
int *pb = NULL;
short * pc= NULL:
long *pd = NULL;
fioat *pe = NULL:
double *pf  = NULL;

指针的类型决定了对指针解引用的时候有多大的权限,也就是能操作几个字节。

例如:char* 的指针解引用只能访问一个字节,而int* 的指针解引用能访问4个字节。


2.指针和数组的关系


很多人都分不清指针和数组的关系,其实,它两没有关系,指针是指针,数组是数组,只不过它两都可以通过'*'解引用或者下标的方式访问元素而已。例如:

int arr[5] = {1,2,3,4,5};
int *p = arr;

这里我们定义了一个指针p,让其指向了数组arr。比如,我们现在想访问2,有两种方式:

(1)通过指针*(p+1).访问,p里面存放的是首元素的地址,加1向后偏移1个整形的大小,找到 2 的地址(指针加 1 ,加的是其所指向类型的大小),再通过 * 解引用得到元素 2.

(2)通过下标 arr[1] 形式访问,实际上这种形式编译器会先把它解析为 *(arr+1)来进行操作。

这里我们应该注意:arr[5] 占20个字节,而P只占4个字节;P本身有自己的地址,而它里面存放的是数组首元素的地址。


3.指针数组和数组指针


指针数组:是数组,是一个存放指针的数组。

char *arr[2] = {"hello","world"};//定义一个指针数组,里面有两个元素,每个元素都是char *类型的指针,这些指针存放着其对应的字符串

    那么arr这个指针数组到底多大呢?对应内存,arr是一个在栈区,拥有两个元素的数组,每个元素又是指针类型,各占4个字节,所以数组大小为8字节。而arr中的"hello","world"存放在只读数据区,arr中的两个指针元素分别存放着这两个字符串的首地址。


数组指针:是指针。

int (*p)[10];

p 先和 * 结合,说明 p 是一个指针变量,它指向的是一个大小为10个整型的数组。

判断 p 是什么类型,看 p 先和谁结合,先和 * 结合是指针,先和[]结合是数组([] 的优先级高于 *)。

应用:

void test()
{
     int arr[3][5] = {0};
     print(arr);
}
void print(int arr[3][5])//第一种方式
{}
void print(int arr[][5])//第二种方式
{}
void print(int (*arr)[])//第三种方式
{}  
我们可以看到在调用print函数时,上面三种形式的参数都可以。得出结论:1.数组传参第一个维度可以被忽略;2.数组传参发生降级,降级为指向其内部元素类型的指针。


4.函数指针、函数指针数组、指向函数指针数组的指针


函数指针

  #include<stdio.h>
  void test()
  {
     printf("haha\n");
  }  
                                                                       
  int main()
  {
     printf("%p\n",test);
     printf("%p\n",&test);
     return 0;
  }                    

输出结果:

可以看出,函数指针就是函数地址,第一条指令的地址,可以为函数名或对函数名取地址。

函数名具有只读属性,只可以作为右值。

例:

void (*pfun1)();//函数指针,里面存放的是函数的地址
void *pfun2();//函数

    如何判断到底是函数还是函数指针,同样,考虑优先级。看先和谁结合,先和 * 结合就是指针,先和()结合就是函数(()优先级高于 * )。

函数指针数组 

函数指针数组:是数组,数组中的每个元素是函数指针。

例:

int (*)()arr[10];

如何判断,还是根据优先级,arr先和[]结合,所以是数组。

函数指针数组的指针

指向函数指针数组的指针:是指针,指向了一个数组,数组中的每个元素都是函数指针。

例;

void (*(*pfun)[10])();
同样是根据优先级判定,pfun先和 * 结合,所以是指针,指向了一个有10个元素的数组,数组里的元素都是函数指针。













  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值