C语言指针②

目录

指针高级

指针的大小

解引用

二维数组知识

指针+二维整型数组

指针+二维字符型数组

指针+指针数组

函数指针

回调函数callback

函数指针

指针函数


指针高级

指针的大小

32位体系系统中,指针变量的大小是4个字节

64位体系系统中,指针变量的大小是8个字节

解引用

解引用:*运算符给出指针指向地址上储存的值。

假设一个指针 p,它存储了一个内存地址。

通过解引用这个指针,可以访问或修改这个内存地址处的值。

二维数组知识

  • C语言中并不存在真正的二维数组
  • 二维数组本质:一维数组的一维数组
  • 二维数组也符合数组的特点——连续性、有序性、单一性

指针+二维整型数组

int a[2][3];        相当于        int [3] a[2];

指针操作二维数组:确定需要定义什么类型的指针?

&a[0]表示起始位置的地址

a[0]——int [3]        a[0]表示数组a的第一行,这是一个int数组,类型是int[3]

&a[0]——int [3]*(理解的形式)&a[0]表示a的第一行的地址,类型是int(*)[3]

正确写法(C语言支持)int(*) [3] 数组类型的指针(数组指针)

int(*p) [3] = a;    p指向二维数组a,p的基类型int[3]

定义指向二维数组的指针        int(*)[列数]

访问数组元素——从数组本质出发理解——逐层访问

*p <=> a[0]    *p相当于a[0](是内部这个一维数组的数组名)

这个表达式表示指针 p 解引用后得到的是数组 a 的第一个元素。

如果 p 指向一个数组的起始地址,那么 *p 就是数组的第一个元素,相当于 a[0]

(*p)[0]

假设 p 是一个指向数组的指针,那么 (*p)[0] 表示:

*p 解引用 p,得到数组的起始地址,相当于数组本身。

(*p)[0] 表示这个数组的第一个元素,相当于 a[0]

*(*p+0) 相当于**p

这个表达式也是在解引用指针 p,并且获取数组的第一个元素:

*p 解引用 p,得到数组的起始地址。

*p + 0 表示数组的起始地址加上偏移量 0,仍然是数组的起始地址。

*(*p + 0) 解引用这个地址,得到数组的第一个元素,相当于 a[0]

**p*(*p),也表示解引用 p 后再解引用一次,得到数组的第一个元素,相当于 a[0]

*(*(p+i)+j)等价于a[i][j]

int a[2][3];

a是一个指向int[3]的指针,int(*)[3]

a[i]是指向第i行的指针        a[i][j]指向第i行第j列元素

将其转换为指针表达式:

a是指向第一个一维数组的指针

a+i是指向第i行的指针

*(a+i)解引用得到第i行,是一个一维数组(也相当于数组名)

*(a+i)+j是指向第i行第j列的指针

*(*(a+i)+j)解引用得到第i行第j列的值

int (*p)[3] = a;有一个指向二维数组的指针

p是一个指向int[3]的指针

p+i 是指向第i行的指针

*(p+i)解引用得到第i行

*(p+i)+j是指向第i行第j列的指针

*(*(p+i)+j)解引用得到第i行第j列的值 这与a[i][j]是等价的

指针+二维字符型数组

定义指向二维字符型数组的指针时,指针的类型应该是 char(*)[列数],其中“列数”是每行数组的长度

char s[][10] = {"hello","world","666"};

char (*p)[10] = s;       

p指向二维数组s,换句话说p是一个指针,指向s中的每一行(即每个字符串)

*(*(p+i)+j)字符型数组与整型数组一致,如上。

指针+指针数组

存放地址数据的数组

指针的数组是一个数组,每个元素都是一个指针

int main(void)
{
    const char*strs[] = {"hello","world","666"};
    const char **p= strs;//p是指向指针数组的指针

    for(int i =0;i<3;i++)
    {
        printf("%s\n",*(p+i));
    }

    return 0;
}

const char **p = strs;声明一个指向数组的指针p,并将其初始化为strs

*(p+i)取出指针数组strs中第i个指针

p+1指向strs数组中的第二个指针,即指向world的指针

*(p+1)解引用得到指向world的指针

*(p+1)+2得到指向world中的第三个字符r的指针

*(*(p+1)+2)解引用得到字符r

函数指针

通过指针的方式来调用函数

函数名代表函数的入口地址:函数名本质上是一个指向函数的指针,它指向函数在内存中的入口地址

int add(int a,int b)函数

函数名对应的数据类型——函数类型int(int a,int b)

返回值int         形参类型int

int(int,int) *p;        理解角度基类型 * 变量名

int(*p)(int,int) ;        正确语法

int(*p)(int,int) = add;        p指向add

*p(1,2);写成p(1,2);        *写不写都没有影响

定义一个函数类型的指针来保存函数的入口地址

通过指针变量进行函数调用

回调函数callback

通过函数指针调用函数就是回调,可以将一个函数作为参数传递给另一个函数,并通过指针调用这个函数

C语言中,使用函数指针实现回调

函数指针

基类型为函数类型的指针

指针函数

返回值为指针类型的函数

char* strcpy(char *dest,char*src);

堆上的空间:

void*malloc(size_t size);

功能:在堆上开辟一块空间

参数:size表示申请空间的大小,单位字节

返回值:成功返回申请到内存空间的地址,失败返回NULL

void free(*ptr);释放函数

释放之前申请的堆上的空间

参数:ptr一定是之前申请到的堆上的空间

free释放后的空间

一般不再使用、指向这块空间的指针是个野指、free之后对应空间上的内容也不要使用

注意:成对出现

free只表示释放空间(这块空间又自由了),但这块空间上的数据不会清零

不要多次free

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值