找回密码
 立即注册
查看: 2169|回复: 28

51单片机函数指针问题

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:127
  • 最近打卡:2025-06-16 10:12:05

3

主题

75

回帖

480

积分

中级会员

积分
480
发表于 2024-6-24 21:01:47 | 显示全部楼层 |阅读模式
#include <stc8h.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char xdata mempool[512]; //声明一个512字节的数组


typedef struct _num {

        char text[100];
        void (*setnum)(void*, char*);
}_num;

_num *num1;

void setnum(_num *num,char  *str)
{
        int i;
        for(i = 0; i <100; i++)
        {
                num->text = *(str+i);
                if (*(str + i) == '\0')
                        break;
        }       
}

_num* Creat_num()
{
        _num* num = (_num*)malloc(sizeof(_num));
        num->setnum = setnum;
        return num;
}

void  main()
{
        init_mempool (&mempool, sizeof(mempool)); //初始化动态内存分配空间

        num1 = Creat_num();//创建一个对象num1

        num1->setnum(num1, "fdsfudsuifgsd\n");//通过setnum函数上设置text中的字符
        printf("%s", num1->text);   //在单片机上面用TFT显示屏显示
        num1->setnum(num1, "wo shi rao ling yun o!!!\n");
        printf("%s", num1->text);
}

这段代码在VS上运行是可以的,但是在51单片机上面就不能用,在单片机上不能通过num1->setnum(num1, "fdsfudsuifgsd\n")这种方式改变text[]的值,通过该函数过后text中的字符是乱码的,如果不通过指针去调用(num1->setnum(_num *num,char  *str))的话单片机就可以正常运行(直接调用setnum(_num *num,char  *str)字符显示正常)。在网上也查询了相应的资料,看得云里雾里的,还是没能解决,请各位坛友帮我解决一下,已经卡在这里半个多月了,麻烦大家了。另外51单片机是可以用动态内存分配的哦 通过这个函数init_mempool (&mempool, sizeof(mempool)); 就可以进行动态内存分配。
小弟先在这里谢谢大家。

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-06-16 00:53:18

0

主题

336

回帖

1628

积分

金牌会员

积分
1628
发表于 2024-6-25 01:05:48 | 显示全部楼层
本帖最后由 xxxevery 于 2024-6-25 01:12 编辑

值得研究一下
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:457
  • 最近打卡:2025-06-16 06:01:58

5

主题

297

回帖

2288

积分

金牌会员

积分
2288
发表于 2024-6-25 07:52:01 | 显示全部楼层
单片机动态分配内存一般用大数组的形式,如果是51的话还要考虑访问方式
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-01 23:18:33

15

主题

139

回帖

1045

积分

金牌会员

积分
1045
发表于 2024-6-25 09:04:29 | 显示全部楼层
这程序绕来绕去的,玩的挺花呀。
你用啥编译的,这能编译通过?

num->text = *(str+i);
是否应该为
num->text[i] = *(str+i);

另外,C51尽量不要用函数指针,和标准C相比,有很多限制。
1. 不要使用函数指针;
2. 如果用函数指针,不要传递参数,参数可以使用全局变量啥的代替;
3. 使用函数指针还想传递参数,必须使用寄存器传递,参数的类型和数量有限制。

num1->setnum(num1, "fdsfudsuifgsd\n");
这句用函数指针间接调用,并且参数还是两个通用指针,超出寄存器所能传递参数限制,编译会出错的。
寄存器传递参数,char型最多3个,如果双字节类型最多也是3个,long或float类型最多一个,通用指针(占3字节)最多一个。
改成直接调用函数,就没有参数数量限制了,除了可以用寄存器传递,还可以使用固定内存地址传递。

如果你用C51开发,我建议程序里不要搞这么多招式,老老实实用C的基本功能就好。
这段程序,如果一定要这么写,把所有用到的指针都改为指定存储类型的指针,这样指针变量占2字节,传递参数应该能放入寄存器了,试试看能不能编译通过。
回复 支持 2 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-06-16 00:53:18

0

主题

336

回帖

1628

积分

金牌会员

积分
1628
发表于 2024-6-25 10:00:38 | 显示全部楼层
学习了
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:127
  • 最近打卡:2025-06-16 10:12:05

3

主题

75

回帖

480

积分

中级会员

积分
480
发表于 2024-6-25 14:31:58 | 显示全部楼层
hea*** 发表于 2024-6-25 09:04
这程序绕来绕去的,玩的挺花呀。
你用啥编译的,这能编译通过?

谢谢你的解答,我的目的是想用面向对象的思想写一个用于51单片机的GUI库,这要写起来比较简单点儿,结果就卡在这个地方了,你还有没有更好的方式来解决这个问题呢?num->text = *(str+i);是该这样的,不知道为啥粘贴上去后面的中括号就没有了。我根据你的思路我重新写了一下。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _obj {

        char id;
        char x;
        char y;
}_obj;

typedef struct _num {
        _obj *obj;
        char text[100];
        void (*setnum)(void*, char*);
}_num;


void setnum(_num *num,char  *str)
{
        int i;
        for(i = 0; i <100; i++)
        {
                num->text = *(str+i);
                if (*(str + i) == '\0')
                        break;
        }       
}

void  Creat_num(_num *num)
{
        //_num* num = (_num*)malloc(sizeof(_num));
        num->setnum = setnum;
       
}
_obj *obj[3];
int main()
{
       
        _num num1;
        _num num2;
        _num num3;
       
         Creat_num(&num1);
         setnum(&num1, "woshiraolingyun");
         Creat_num(&num2);
         setnum(&num2, "woshiliukun");
         Creat_num(&num3);
         setnum(&num3, "woshirakey");
         obj[0] = &num1;
         obj[1] = &num2;
         obj[2] = &num3;
         for (int i = 0; i < 3; i++)
         {
                 printf("%s\n",((_num*)(obj))->text);
         }
        return 0;
}
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:127
  • 最近打卡:2025-06-16 10:12:05

3

主题

75

回帖

480

积分

中级会员

积分
480
发表于 2024-6-25 16:42:49 | 显示全部楼层
hea*** 发表于 2024-6-25 09:04
这程序绕来绕去的,玩的挺花呀。
你用啥编译的,这能编译通过?

我的代码在KEILC51中能编译通过,程序都能正常运行,就是是函数指针间接调用的时候(num1->setnum(num1, "fdsfudsuifgsd\n"))这一句不能正常运行,通过它设置text的值后显示为乱码,我刚刚又去查了很多资料,说的是函数指针间接调用参数不能超过三个,但是我这里只有两个参数啊。另外num->text = *(str+i);我的源程序中是有中括号的,但是粘贴上来就没有了。固定内存地址传递这个怎么弄呢?谢谢
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-06-16 10:02:39

33

主题

2447

回帖

5168

积分

论坛元老

积分
5168
发表于 2024-6-25 17:02:35 | 显示全部楼层
rayr*** 发表于 2024-6-25 16:42
我的代码在KEILC51中能编译通过,程序都能正常运行,就是是函数指针间接调用的时候(num1->setnum(num1,  ...

我觉得吧,,setnum之后用串口打印出来,,看看里面是不是你写的东西,,还不排除是不是后面的屏幕显示的问题呢
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:127
  • 最近打卡:2025-06-16 10:12:05

3

主题

75

回帖

480

积分

中级会员

积分
480
发表于 2024-6-25 17:12:09 | 显示全部楼层
_奶*** 发表于 2024-6-25 17:02
我觉得吧,,setnum之后用串口打印出来,,看看里面是不是你写的东西,,还不排除是不是后面的屏幕显示的 ...

这段代码在VS上面没有问题没在单片机上面不能正常运行,运行 (num1->setnum(num1, "fdsfudsuifgsd\n");//通过setnum函数上设置text中的字符 )这段代码后,不能正常的把值传递给text,显示出来时乱码,如果直接调用   setnum(num1, "fdsfudsuifgsd\n"),就能正常显示出来。

点评

看我下面测试的截图吧  发表于 2024-6-25 17:37
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-06-16 10:02:39

33

主题

2447

回帖

5168

积分

论坛元老

积分
5168
发表于 2024-6-25 17:29:39 | 显示全部楼层
截图202406251728434371.jpg
0.0 我试着函数指针用的是可以的0.0  动态分配内存的方式没用测,,
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-16 13:04 , Processed in 0.148311 second(s), 106 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表