C语言——函数指针类型转换

  昨天为了避免跨层调用API搞了个回调函数,用了函数指针,因为参数类型的问题总是编译报错,今天就看了两篇博文学习学习,顺便做做笔记。

  其实正常来讲只要把函数指针的参数个数、类型和返回值这些函数指针的标签或者说是属性写对了的话就不会有社么问题,但我也不知道怎么着就会报错【擦汗】

  正好趁着这个机会好好了解一下函数的用时的栈空间和函数指针的使用。

1、函数指针

  函数名本就是一个常量指针常量,指向代码区的函数本体,带有一些属性(标签),就类似于“ int * ”带有的属性是“ int ”。

  函数指针是和某个函数带有相同属性的指针,函数指针被赋值后同样指向代码区的函数本体。

  更改函数指针的属性(参数、返回值)并不影响这个指针指向函数本体。

2、参数传递

  猜测在同一线程中所有函数传参使用的栈空间的起始地址都是同一个。

同一线程:

 1 #include <stdio.h>
 3 
 4 void fi3(int a, int b, int c)
 5 {
 6     printf("fi3:\t");
 7     printf("%d, %d, %d\n", &a, &b, &c);
 8 }
 9 
10 void mpp(int a, int b,int c)
11 {
12     printf("mpp:\t");
13     printf("%d, %d, %d\n", &a, &b, &c);
14 }
15 
16 
17 int main()
18 {
19     void (*I3)(void) = (void (*)(void))fi3;
20     I3();
21     mpp(7,8,9);
22     return 0;
23 }
24 
25 编译运行:
26 PS F:\tinyxml_2_6_2\tinyxml> gcc .\main.cpp -o pmain
27 PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe
28 
29 输出结果:
30 fi3:    6422272, 6422276, 6422280
31 mpp:    6422272, 6422276, 6422280

 

不同线程:

#include <stdio.h>
#include <pthread.h>

void mpp(int a, int b,int c)
{
    printf("mpp:\t");
    printf("%d, %d, %d\n", &a, &b, &c);
}

void *pthreadFun(void *arg)
{
    mpp(7,8,9);
}


int main()
{
    float val1 = 1.23;
    float val2 = 2.34;
    void *statRet = nullptr;
    pthread_t tid[2] = {0};
    pthread_create(&tid[0], nullptr, pthreadFun, (void *)&val1);
    pthread_create(&tid[1], nullptr, pthreadFun, (void *)&val2);
    pthread_join(tid[0], &statRet);
    pthread_join(tid[1], &statRet);
    return 0;
}

编译运行:
PS F:\tinyxml_2_6_2\tinyxml> gcc .\main.cpp -o pmain -lpthread
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe

输出:
mpp:    15597240, 15597244, 15597248
mpp:    17694392, 17694396, 17694400

此处贴图表示线程内函数参数栈空间(我用的是Windows的gcc的编译环境,地址):

 3、函数调用

  调用函数时会先将函数形参复制到参数栈空间中,再执行代码区中的函数体。

  函数参数是存在最小传递单位的,这里是4字节,可能与进程4G地址空间或是32位CPU带宽是4byte有关系,这里先留个坑。

  每次调用函数参数栈空间中的数据不会被全部置位,而是用到那个单元格的空间就把那个单元格(最小单位)的空间用新的参数覆盖。

#include <stdio.h>

void fc3(char a, char b, char c)
{
    printf("fc3:\t");
    printf("%d, %d, %d\n", a, b, c);
}

void fi3(int a, int b, int c)
{
    printf("fi3:\t");
    printf("%d, %d, %d\n", a, b, c);
}

int main()
{
    fc3(1, 2, 3);
    void(*F3)(int) = (void (*)(int))fi3;
    F3(66);
    return 0;
}

编译运行:
PS F:\tinyxml_2_6_2\tinyxml> gcc .\main.cpp -o pmain
PS F:\tinyxml_2_6_2\tinyxml> .\pmain.exe

输出结果:
fc3:    1, 2, 3
fi3:    66, 2, 3

 

关于三篇大佬的博客:

函数栈帧(详细图解)_函数调用栈帧过程(带图详解)-CSDN博客

关于函数指针类型强制转换的一些摸索-CSDN博客

函数指针的强制类型转换与void指针_函数指针的强制转换-CSDN博客

posted on 2024-01-16 15:13  _燃灯续昼  阅读(408)  评论(0编辑  收藏  举报

导航