C语言——函数指针类型转换
  I0Qo175BtL7p 2024年01月16日 21 0

  昨天为了避免跨层调用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博客

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年01月16日 0

暂无评论

推荐阅读
  TKwJ4YzyA8uz   2024年05月17日   41   0   0 C语言
  6Df3JnWQUC5m   2024年04月24日   55   0   0 C语言
  fHBiUfJyY67V   2024年04月26日   41   0   0 C语言
  V88gxnVgnp1F   2024年05月08日   90   0   0 C语言
  6Df3JnWQUC5m   2024年05月08日   81   0   0 C语言
  o1ZcTI9mJsxK   2024年05月08日   121   0   0 C语言
  H5oyQecqjP4R   2024年04月26日   38   0   0 C语言
  6Df3JnWQUC5m   2024年04月25日   48   0   0 C语言
  nmX9dIiR6BtA   2024年04月28日   45   0   0 C语言
  6Df3JnWQUC5m   2024年05月17日   51   0   0 C语言
  6Df3JnWQUC5m   2024年04月25日   50   0   0 C语言
I0Qo175BtL7p
作者其他文章 更多