【问题标题】:Function pointer to assembly label指向程序集标签的函数指针
【发布时间】:2021-12-29 12:29:19
【问题描述】:

当尝试从 C 中的函数(在另一个文件中)调用汇编文件中的标签 _exit 时,这些语句有什么问题?我将 _exit 的第一条指令视为函数指针,而不是预期的行为!编译器是gcc。

typedef void (*exit_f)(void);
extern exit_f _exit;

main() {
...
exit_f exit = (exit_f)_exit;
...
exit();

【问题讨论】:

  • 您已将_exit 声明为指向函数的指针。为什么你不期望它被视为一个函数的指针?
  • 相关:calling assembly function from c 展示了一些使用原型以正常方式声明 asm 函数的示例。

标签: assembly function-pointers typedef extern


【解决方案1】:

typedef void (*fp_type)(void);fp_type 声明为函数指针;所以,fp_type fp; 使 fp 成为一个函数指针,如果你调用它,这就是它的行为方式。函数指针是一个变量,作为一个全局变量 (extern),通常期望在数据部分中,作为一个指针变量,其内容然后引用某个函数(在文本/代码中)。因此,编译器将获取指针变量的值,然后用它进行间接调用。

如果汇编部分中提供的标签不是指向代码的指针,它会搞砸,C 代码或汇编代码应该更改,以便它们都同意标签是代码(函数)还是数据(一个函数指针变量)。

在 C 中,您不需要取消引用函数指针;简单地应用调用将隐式取消引用它。所以,fp();(*fp)() 是相同的,它们都将访问该函数指针变量以获取其内容:函数地址,并调用该地址引用的函数(通过间接函数调用)。

如果它只是一个函数(而不是函数指针),那么声明它:typedef void f_type(void);f_type f;。这样,f(); 将简单地调用函数而不访问任何变量((*f)(); 将执行完全相同的操作;取消引用在那里被有效地忽略了)。


如果是我,而我们只想从 C 中调用程序集,我会放弃 main 中不必要的 typedef 和函数指针局部变量,并简单地声明函数:extern void _exit(void);,稍后调用为 _exit(); .

名义上,即使你想要main 中的函数指针局部变量,我也会声明_exit,因为这似乎更合适:extern void _exit(void);——如果需要,你仍然可以使用函数指针(exit_f exit = _exit; )

在任何情况下,(exit_f) 中应用的 ... = (exit_f) _exit 中的强制转换是不必要的,避免不必要的强制转换是好的,因为这将有助于编译器对错别字等给出错误/警告。

【讨论】:

  • 非常感谢您的回答!我同意代码中有很多冗余。剩下的问题是为什么在这里转换为相同类型(exit_f)被认为是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
相关资源
最近更新 更多