首页 > 其他分享 >C语言——函数指针类型转换

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

时间:2024-01-16 15:24:40浏览次数:25  
标签:类型转换 mpp int void C语言 tinyxml printf 函数指针

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

标签:类型转换,mpp,int,void,C语言,tinyxml,printf,函数指针
From: https://www.cnblogs.com/GREEN-FIEID/p/17967174

相关文章

  • C语言入门-printf库函数
    printf()库函数调用格式:printf("<格式化字符串>",<参量表>);声明intprintf(constchar*format,...)参数格式字符意义a,A以十六进制形式输出浮点数(C99新增)。实例printf("pi=%a\n",3.14);输出pi=0x1.91eb86p+1。d以十进制形式输出带符号整数(正数不......
  • 双向链表C语言实现
    双向链表实现(带头结点版)双向链表的实现与单链表类似,在这里使用C语言实现,主要包括头插法插入节点,删除节点以及创建空链表抽象数据结构ADT定义双向链表与单链表的区别在于多了一个指向上一个节点的指针prevtypedefstruct_Node{intdata;struct_Node*next;......
  • 【数据结构】C语言实现共享栈
    共享栈通过C语言实现导言大家好,很高兴又和大家见面啦!!!在上一篇内容中,我们介绍了如何通过C语言实现顺序栈,并且在介绍顺序栈的进栈操作时有提到过我们可以通过选择数组的首元素或者尾元素作为栈底,来进行栈的创建,以及栈的另一种形式——链栈。根据前面的介绍,我们知道了顺序栈是通过静......
  • C语言用数组实现三子棋
    //game.hdefineROW3defineCOL3include<stdio.h>voidInitBoard(charboard[ROW][COL],introw,intcol);voidDisplayBoard(charboard[ROW][COL],introw,intcol);//game.cinclude"game.h"voidInitBoard(charboard[ROW][COL],introw......
  • C语言学习随笔-07 auto关键字
    1、在C中auto是一个存储类的关键字。     -auto存储类:auto存储类是所有局部变量默认的存储类。     -auto可以在声明变量的时候根据变量的初始值的类型自动为此变量选择匹配的类型。2、注意事项     -auto声明的变量必须要初始化,否则编译器不能判断变量......
  • C语言---Day6
    15、enum枚举---枚举是C语言中的一种基本数据类型,用于定义一组具有离散值的常量,它可以让数据更简洁,更易读;通常用于为程序中的一组相关的常量取名字,以便于程序的可读性和维护性---声明枚举类型enumDay{MON=1,TUE,WED,THU,FRI,SAT,SUN};---枚举变量的定义:先......
  • Arduino部分C语言含义之--“::”
    "::“在C++中表示作用域,和所属关系。”::"是运算符中等级最高的。有三种作用。1.作用域符号例如:A,B表示两个类,在A,B中都有成员member。那么:A::member就表示类A中的成员member。B::member就表示类B中的成员member。2.全局作用域符号charzhou;//全局变量voids......
  • 【数据结构】C语言实现顺序栈
    顺序栈的C语言实现导言大家好,很高兴又和大家见面啦!!!在上一个篇章中,我们介绍了栈的基本概念,以及栈中的重要术语。通过介绍我们知道了栈的本质也是一种线性表,只不过它是一种操作受限的线性表。因此栈的实现方式与线性表的实现实际上是大同小异的。下面我们就来介绍一下如何通过C语言......
  • C语言文件操作
    写文件-输出相应字符/字符串到相应的文本文件#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>#include<errno.h>#include<string.h>intmain()//输入字符到TEST.txt中{ FILE*pfwrite=fopen("TEST.txt","w"); if(pfwrite==NULL)//打开失败情况 { prin......
  • 本周(2024.1.8-2024.1.14)C语言学习小结
    既然之前说了要尝试坚持写博客,那就试试吧。本周花在C语言上的时间不多,简要回顾一下。动态数组学习并实践了基本的动态数组知识,即calloc、malloc、relloc、free。以下是基本综合所学内容写的代码,实现动态数据添加。#include<stdio.h>#include<stdlib.h>intmain(){......