C语言学习笔记【03】——指针与函数

        我们知道在函数之间可以传递变量的值,在函数之间同样可以传递地址(地址)。函数与指针之间有着密切的关系,包含三种含义:指针作为函数的参数,函数的返回值为指针以及指向函数的指针。

目录

指针函数

函数指针

typedef与函数指针

万能指针充当函数指针


指针函数

        一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个[指针]变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。

指针函数就是用到了指针的函数,本质就是一个函数

  • 指针当作函数参数(如何修改实参)

  • 指针当作函数返回值

1. 改实参

void modify(int count)
{
    count=111;
}
int main()
{
    int count=1;
    modify(count);
    printf("%d\n",count);
    
    return 0;
}

 数值的传递都是通过赋值进行的。因为主函数和子函数所存储数据位置不一样,所以主函数main( )的变量count的值没有被更改(覆盖)。也就是说子函数modify( )中的变量count的值改变了,但不影响主函数。如果我们使用指针传地址呢?

void modifyCount(int* p)
{
    *p=999;
}
int main()
{
    int count=1;
    modifyCount(&count);
    printf("%d\n",count);
    
    return 0;
}

int* p=count这样的话类型不一致,所以要使用&来取地址,即址传递。

 

 2.当作返回值

不能返回局部变量的地址,比如下面是错例因为局部变量的内存会被回收掉。如果申请的是堆区的内存就不会被回收掉。

int* returnPoint()
{
    int num=100;
    return #
}
int main()
{
    int* result=returnPoint();
    printf("%d\n", *result);
    printf("%d\n", *result);
    printf("%d\n", *result);
    return 0;
}

有些编译器会优化这个操作,所以第一次访问时会保留数值,但多访问几次就会输出一个垃圾值。

 

函数指针

函数指针:指向函数的指针。

  • 用来调用函数

  • 函数名就是函数指针(有点特殊,不同于指针函数)

int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int a=5,b=3;
    printf("%d\n",max(a,b));
    printf("%p\n",max);
    printf("%p\n",&max);
    return 0;
}

 

  • 定义

    int (* pFunc)(int ,int ) //int (* pFunc)(int a ,int b )

    (*指针名)替换函数名,回调函数也一样

  • (*指针名)替换函数名 剩下照抄,形参名可以省略,就是函数指针

int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int a=5,b=3;
    int (*pFunc)(int,int)=NULL;
    pFunc=max;//等效于pFunc=&max;
    printf("%d\n",pFunc(a,b));
    printf("%d\n",(*pFunc)(a,b));
    return 0;
}

  • 通过和函数指针调用函数

    • 直接用指针名替换函数去调用函数

    • (*指针名)替换函数名调用函数

typedef与函数指针

typedef基本用法

  • 给类型取别名

    typedef int 整数,整数就是int的别名,功能一样

typedef int 整数;
int a1=1;
整数 a2=1;
printf("%d\n",a1);
printf("%d\n",a2);

 注意,加深难度

typedef int ARRAY[3];
ARRAY array[3]={1,2,3,4,5,6,7,8,9};
for(int i=0;i<3;i++)
{
    for(int j=0;j<3;j++)
    {
        printf("%d\t",array[i][j]);
    }
    printf("\n");
}

 

如何看懂(还原)别名呢?

找到定义别名的语句,删掉typedef,定义名替换别名。操作如下

  • 找到定义别名的语句,删掉typedef

typedef int ARRAY[3];
 int ARRAY[3];

定义的名字(array[3])替换别名(ARRAY)

 int array[3][3];
    • 还原之后就是正常情况下,定义二维数组

      • 该实例中的ARRAY[3],定义就是一个一维数组

  • typedef与函数指针

    typedef给函数指针取别名

int max(int a, int b)
{
    return a > b ? a : b;
}
typedef int(*P)(int, int);
int main()
{
    P p=max;
    printf("%d\n", max(3, 5));
    printf("%d\n", p(3, 5));
    return 0;
}

万能指针充当函数指针

  • 万能指针:使用必须做强制类型转换

  • 指针类型:去掉变量名

void print()
{
    printf("abcd\n");
}
int main()
{
    void* p=print;
    ((void(*)())p)();
    return 0;
}

 

  • 正常调用:p()

  • void*指针使用必须要做类型转换

    ( ( 指针类型 ) p ) ( )

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值