C语言——指针函数和函数指针

目录

一、指针函数

1.有效性

2.参数传递

二、函数指针

1.应用

2.typedef

3.二级指针

4.const指针


一、指针函数

返回值为指针的函数

C 语言中,栈上的局部变量会在函数执行结束后被销毁,因此不能直接返回其地址。若需返回局部变量相关的数据,可通过以下三种方式调整:

  1. 给局部变量添加 static 关键字;
  2. 使用全局变量;
  3. 通过 malloc 函数将内存空间开辟到堆上。

1.有效性

C 语言中函数返回指针时,不同变量存储区域对指针有效性的影响:

  1. 返回栈上局部数组的地址(无效)
    1. 函数 char* Fun() 中定义了局部数组 char a[50] = "hello",该数组存储在栈上。
    2. 函数执行结束后,栈空间被释放,数组 a 的内存被回收。
    3. main 函数中接收的指针 p = 0x5000 指向的是已失效的栈内存,后续访问该地址属于 “野指针” 操作。
  2. 返回静态数组的地址(有效)
    1. 函数 char* Fun() 中定义了静态数组 static char a[50] = "hello",静态变量存储在静态数据区(.data 段)。
    2. 静态数据区的变量生命周期与程序一致,函数执行结束后不会被销毁。
    3. main 函数中接收的指针 p = 0x300 始终有效,可安全访问数组内容。
  3. 返回字符串常量的地址(有效)
    1. 函数 char* Fun2() 中定义了字符串常量 char* p = "hello",字符串常量存储在只读数据区(.rodata 段)。
    2. 只读数据区的内容在程序运行期间不会被修改且一直存在。
    3. main 函数中接收的指针 str = 0x100 可长期有效访问该字符串(但注意字符串常量不可修改)。

2.参数传递

指针函数返回的地址,可以作为下一个函数的参数进行传递。

int main()
{
    char src[100] = {0};
    char dst[100] = {0};
    strcpy(dst,strcpy(src,"hello")); //内部的strcpy调用完后,会返回src指针。
    printf("src :%s ,dst:%s\n",src,dst);
}

二、函数指针

指向了一个函数的指针

1.应用

降低耦合度,增加灵活性。

在代码开放阶段,函数需要执行的功能不确定。需要等到程序运行起来后,才能确定具体功能。 这里的 add,sub 会在程序运行起来后,根据不同情况会被调用。add,sub 被称为回调函数。

int add(int a, int b) // int (int,int) 0x3000 这个函数的类型,就是去掉函数名
{
    return a+b;
}

int sub(int a, int b) // 0x5000
{
    return a-b;
}

int main() // 函数名,本质是就是一个指针,指向的内容是一段操作,不是数据而已。
{
    int (*op)(int,int) = NULL; // int(*)(int,int) 定义了一个函数指针
    int a = 10;
    int b = 20;
    int num = 0;

    printf("1:+ 2:-\n");
    printf("input num:");
    scanf("%d",&num);

    switch(num)
    {
    case 1:
        op = add; // op = 0x3000 函数指针的赋值
        break;
    case 2:
        op = sub; // op = 0x5000
        break;
    default:
        op = add;
}

int ret = op(a, b); // 函数指针的调用

printf("op result is %d\n", ret);
return 0;
}

2.typedef

定义类型别名

typedef unsigned int u32; // u32 是一个类型名 等价 unsigned int
typedef int s32;

typedef int (*PFUN)(int,int); // PFUN 是一个类型名,int(*)(int,int)
PFUN op1 = NULL; // 等价于 int(*op1)(int,int) = NULL;
op1 = lessthan;

3.二级指针

指向指针变量的指针

二级指针变量中存储的是一个地址,在解引用后,存储的还是一个地址

应用:在被调函数中,需要修改指针的指向。

#include <stdio.h>

void fun(char **arg_p) 二级指针
{
    *arg_p = "ok"; // 这个使用间接引用,直接操作main函数中的一级指针变量本身
}

int main()
{
    char *p = "hello"; // int *
    fun(&p); // &p int **p; &p是二级指针
    printf("p is %s\n",p);
}

//char *p ="ok";
//char **q = &p;

4.const指针

被 const 修改的变量,称为只读变量

规则:const 靠近谁,谁就不能被修改。

  • 若 const 在 * 左边,修饰数据,数据不能改,指针可以改指向;
  • 若在 * 右边,修饰指针本身,指针不能改指向,数据可以改。
  • 若左右都有,数据和指针指向都不能改
声明形式修饰对象能否改数据?能否改指针指向?是否需初始化?
const char *p; 指向的数据
char const *p;指向的数据
char *const p;指针变量本身
const char *const p;数据 + 指针本身
char const *const p;数据 + 指针本身
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值