【发布时间】:2021-08-19 10:38:28
【问题描述】:
我正在用 g++ 编译一个应用程序,该应用程序调用“C”库中定义的一些函数。 我需要调用的一些函数在原始“.c”文件中被定义为静态(我知道当一个函数被定义为静态时,它不会从该文件外部调用,但尽管如此,我需要从外部调用它们)。
我将使用指向函数的指针从该文件外部执行它们并查看它们如何工作,我准备了这个示例,我想在 file_2.c 中执行 file_1.c 中定义的静态函数 fun5 和 fun6
file_1.h
--------
#ifndef FILE_1_H
#define FILE_1_H
int (*getPtrFun6(void*))(int,char,char*);
#endif
file_1.c
--------
#include <stdio.h>
int(*ptr_fun5)(int,int);
static int fun5(int p1, int p2)
{
printf("fun5 called.\n");
ptr_fun5 = &fun5;
return p1 + p2;
}
static int fun6(int p1, char p2, char* p3)
{
printf("fun6 called with p1 = %d, p2 = %c, p3 = %s.\n", p1, p2, p3);
return p1;
}
int (*getPtrFun6(void*))(int,char,char*)
{
return fun6;
}
file_2.c
--------
#include <stdio.h>
#include <cstring>
#include "file_1.h"
extern int(*ptr_fun5)(int,int);
extern int(*ptr_fun6)(int,char,char*);
int main(void)
{
int returnValue = 0;
// To run fun5
returnValue = (ptr_fun5)(15, 32);
printf ("Returns %d\n", returnValue);
// To run fun6
char myString[50];
memset(myString,0,50);
strncpy(myString,"THIS IS OK",10);
ptr_fun6 = getPtrFun6();
returnValue = (ptr_fun6)(32, 'v', myString);
printf ("Returns %d\n", returnValue);
return 0;
}
我用命令编译程序:
g++ file_2.c file_1.c -o static_example
从源代码中可以看出,我尝试了两种不同的方式来使用指向静态函数的指针。
如果我在源代码中对 fun6 的所有内容发表评论,编译并运行它(只需调用 fun5)我会收到错误“分段错误”。
另一方面,如果我在源代码中对所有与 fun5 相关的内容进行注释并只留下 fun6,则在编译程序时会出现以下错误:
file_2.c: In function ‘int main()’:
file_2.c:20:25: error: too few arguments to function ‘int (* getPtrFun6(void*))(int, char, char*)’
ptr_fun6 = getPtrFun6();
^
In file included from file_2.c:4:
file_1.h:4:7: note: declared here
int (*getPtrFun6(void*))(int,char,char*);
^~~~~~~~~~
我查看了网络上的各种论坛和教程,但我没有看到错误是什么,所以我需要一些帮助来正确使用指向 fun5 和 fun6 的指针。
【问题讨论】:
-
当您使用调试器一步一步地运行程序时,一次一行,您的调试器向您展示了什么?
-
如果一个函数是静态的,那么它并不意味着从任何其他编译单元调用。它是该文件的本地文件。如果您需要在其他编译单元中调用该函数,您只需删除 static 关键字并使其具有外部链接即可。这整个指针业务看起来很可怕
-
这有点太宽泛了,@MoNazemi。允许通过函数指针从不同的编译单元调用静态函数,并且它有一些合理的用例。当然这不是一个普通人应该做的,但
static在技术上是关于函数标识符的链接,并且只是间接地关于从哪里可以调用它。 -
@MoNazemi 在这种情况下,是的,全局变量是非常糟糕的设计。但一般来说,在某些情况下,将函数指针返回到内部实现是一个好主意。这是私有封装的一种方式。
-
顺便说一句,从
#include <cstring>来看,您似乎将这些文件编译为 C++。如果您有一个正确支持 C 的编译器,您可能希望将其更改为#include <string.h>并确保您的编译器编译为 C,而不是 C++。两种语言之间存在差异,将 C 源代码编译为 C++ 会在学习时造成混淆。
标签: c++ c static function-pointers