【问题标题】:How to assign base address for a function pointer returning enum?如何为返回枚举的函数指针分配基地址?
【发布时间】:2016-08-16 11:56:59
【问题描述】:

我有一个返回枚举的函数指针
我的枚举是

typedef enum {    
    FIRST,    
    SECOND,  
    THIRD  
} STATUS;  

在代码中,有人试图将基地址分配为

STATUS (*start_port)(void *,void *)= 0x80000001;

但它正在抛出警告

“初始化使指针从整数不进行强制转换”

还有

“ISO C90 禁止混合声明和代码 [-Wdeclaration-after-statement]”

我把声明分开了

STATUS (*start_port)(void *,void *);

然后尝试通过以下方式将地址分配给函数指针

start_port = (unsigned int *)0x80000001;

它更正了混合声明警告,但出现了一个新错误

“来自不兼容指针类型的赋值”

当返回值为枚举时,我想知道如何正确地将函数指针类型转换为固定(常量)基地址。

【问题讨论】:

  • 所以你要调用的函数的代码实际上是在地址0x80000001?
  • 变量start_port是一个指向函数的指针。您必须将值转换为正确的类型。
  • 回复。 c90 警告:使用标准 C,即 C11,或至少是现代 C99。除非您真的必须维护一些旧代码,否则不要使用 mideval C90。
  • @Olaf 一些较小的嵌入式平台(我猜 OP 正在使用,考虑到初始化)没有最新的编译器。
  • @achoora:关于编译器还是 C 版本?无论如何,有了这样的镇流器,你必须忍受这个。只需按照错误消息进行操作即可。但是您不能将整数或对象指针合规地转换为函数指针。所有版本都是如此。

标签: c pointers enums


【解决方案1】:

正如其他答案中所述,您必须使用显式强制转换将整数转换为函数指针:

STATUS (*start_port)(void *,void *)= (STATUS(*)(void *,void *))0x80000001;

但是函数指针很难阅读。使用typedef 让它们更干净:

typedef STATUS FuncType(void*, void*);
  ...
FuncType * start_port = (FuncType *)0x80000001;

【讨论】:

  • 这只是个人意见。如果只有一个该类型的函数,typedef 几乎没有用处。只要考虑这是一个跳转表。
  • @Olaf typedef 即使是单次使用也会使代码更加清晰。立即知道指针的预期用途是什么。
  • 废话。您仍然需要检查两个地方。如果您打算更改多个功能的界面,typedefs 是有意义的。但是这里不太可能,即使有多个函数(jump-table),更有可能不想改变所有函数的接口,而是一个单一的。因此,无论如何,每个指针都需要一个typedef看看,你的回答有多自以为是?
  • @Olaf C 函数指针语法并不是世界上最漂亮的。与上面的括号混乱相比,Typedef 使其更容易理解,尤其是对于初学者。无论如何, typedef 只是一个奖励:答案的核心是你需要一个演员。您正在提出比实际更大的问题。
  • 这个答案中推荐的方法几乎是使用函数指针的事实上的标准方法。不管你喜不喜欢,这就是大多数使用函数指针的库的设计方式。这里唯一的风格是你 typedef 一个函数类型,如本例所示,或者你 typedef 一个函数指针类型。我个人更喜欢前者,因为这使得 typedef:ed 函数指针的外观和行为与普通指针一样。
【解决方案2】:
  1. 你声明了start_port类型的函数指针,然后尝试分配一个unsigned int *指针给它,试试

    STATUS (*start_port)(void *,void *) = (STATUS (*)(void *,void *)) 0x80000001;
    

    但这是一种糟糕的风格,你不应该这样做。

  2. 这是一个警告,告诉您不要在代码中声明变量,这对于现代版本的 标准不再是问题,但恕我直言仍然是一个好习惯。在代码中添加变量会使遵循算法和逻辑变得更加困难。而仅在块的开头声明它们可以更容易地阅读整个代码。你知道声明在哪里,你不需要跳过只是“声明”的部分代码。

  3. 和(1)一样的问题,所以正确的施法是

    start_port = (STATUS (*)(void *,void *)) 0x80000001;
    

【讨论】:

  • 变量声明应尽可能接近用法(例如在使用它的循环之前)。当您必须一直上下跳跃以检查变量类型或变量的来源时,冗长的函数可能会让人难以阅读
  • 冗长的函数已经是一团糟了。如果你有一个冗长的函数,除了放置声明的位置之外,你还有更多的事情要担心。函数体至少应该适合编辑器的缓冲区,如果它更长,唯一合理的解释是很长的switch 语句。否则,无论你在哪里声明变量,都很容易出现错误。
  • 感谢您的快速回答这真的让我很开心
猜你喜欢
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多