C 转换为函数指针时出现编译器错误

C 转换为函数指针时出现编译器错误,c,embedded,C,Embedded,我正在使用HiTech的PICC32编译器(类似于C90)为PIC32MX编写一个引导加载程序。在某个时候,我需要跳转到真正的主例程,所以在引导加载程序中的某个地方我有 void (*user_main) (void); user_main = (void (*) (void)) 0x9D003000; user_main(); (注意,在实际代码中,函数签名是typedef'd,地址是宏。) 我宁愿从物理地址计算该(虚拟)地址,并有如下内容: void (*user_main) (void)

我正在使用HiTech的PICC32编译器(类似于C90)为PIC32MX编写一个引导加载程序。在某个时候,我需要跳转到真正的主例程,所以在引导加载程序中的某个地方我有

void (*user_main) (void);
user_main = (void (*) (void)) 0x9D003000;
user_main();
(注意,在实际代码中,函数签名是typedef'd,地址是宏。)

我宁愿从物理地址计算该(虚拟)地址,并有如下内容:

void (*user_main) (void);
user_main = (void (*) (void)) (0x1D003000 | 0x80000000);
user_main();
…但当我尝试这样做时,会出现编译器错误:

Error #474: ; 0: no psect specified for function variable/argument allocation
我是否在这里被一些奇怪的C语法绊倒了

这个错误没有引用任何特定的行,但是如果我注释掉
user\u main()
调用,它就会消失。(这可能是编译器删除了冗余代码分支,但HiTech PICC32在Lite模式下并不特别智能,因此可能不是。)

更新:我还注意到如果我使用

void (*user_main) (void);
unsigned int x = 0x9D003000;
user_main = (void (*) (void)) x;
user_main();

我得到了同样的错误。

当您删除对函数的调用时,编译器删除冗余代码的操作可能是正确的。我认为GCC-S将为您提供程序集输出,在删除函数调用站点后,您可以使用它来确认函数定义的缺失


我想这将有助于您进行调试…

一种丑陋的方法可能是将指针类型和未签名的long放在一个并集中。你知道你需要做什么。C标准会产生这种未定义的行为,但您已经处于未定义的领域,一旦您需要将整数转换为指针,编译器就会对您进行处理。

这不是一般的C问题,而是高科技特有的问题

我从未使用过高科技产品,但问题似乎是链接器不知道应该将
user\u main
例程的参数或局部变量放在内存中的什么位置。从:

(474) 没有为函数变量/参数分配指定psect(链接器)

从未见过向链接器指定有关自动/参数块信息的FNCONF汇编指令。如有必要,这将在标准运行时文件中提供。此错误可能意味着未链接正确的运行时STARTOF模块。如果运行时启动模块是手工编写的,请确保使用了FNCONF指令


我意识到这不是原始问题的答案,但通过指向函数的指针调用函数的语法可以通过以下构造变得更清晰(正确):

(*user_main)();

如果这样做,您会立即看到user_main是一个被取消引用的指针,并执行一个函数调用。这避免了将指向函数的user_main指针与user_main()函数混淆。

很抱歉回答我自己的问题,但这是编译器中的一个错误。他们向我发送了一个更新的版本,修复了这个问题。

这个特定的编译器完全支持类型双关(我已经检查过了),但是为什么它可以用于文本
0x9D003000
,而不是
(0x1D0003000 | 0x8000000)
?实际上,与其在这里讨论这个问题,如果这不是一个明显的C问题,我就联系HiTech。顺便说一句,不管你最终如何说服你的编译器理解你的代码,我都会做一个无关的更改来帮助人们理解你的代码。typedef void(*user_main_t)(void);用户主=(用户主)0x9D003000;哦,是的,我实际上在头文件中有一个
typedef void(*main函数)(void)
。函数typedef是我最喜欢的C功能之一;)