在同一个头文件中声明函数指针后使用extern的优点

Advantages of using extern after the declaration of fucntion pointer in the same header file

在下面的代码中,是否可以解释为什么在声明函数指针之后就使用了extern。

myfuncs.h

typedef void    (*initMyfuncs_t)(Init_t*, CallBacks_t *,result_t*);
extern initMyfuncs_t _initMyfuncs;

我们正在 myfunc.c 文件中使用它

void *glbfuncs=NULL
glbfuncs = dlopen("glbfuncs.so",RTLD_NOW);
initMyfuncs_t _initMyfuncs=NULL;
_initMyfuncs = dlsym(glbfuncs, "_initMyfuncs");

通常,我们在使用该函数指针或变量的文件或其他头文件中使用extern。 这里我们在头文件中声明了 extern 并在同一个源文件中使用它。 这里用extern有什么用

并且这个函数指针在没有外部声明的情况下被其他源文件使用。我对此感到困惑?通常,我们在某个地方有一个声明(somehere.h),如果我们在其他文件(here.h 或 here.c)中使用它,我们使用 extern 关键字只是为了获取这个变量。

我不是很明白在typedef之后使用extern关键字的原因。

为什么我们在同一个头文件中声明函数指针后使用extern。

需要extern关键字来区分函数指针等全局数据对象的声明和该对象的定义。

在头文件中,您应该只有声明。定义属于源文件,不应在不同的源文件中重复。如果将定义放在头文件中,最终会在 link 次得到相同符号的多个定义。由于历史原因,如果普通 linker 没有初始值设定项,他们会接受这些多重定义。然而,这被认为是不好的做法,应该避免。

myfuncs.h

extern initMyfuncs_t _initMyfuncs; // declaration of function pointer

myfuncs.c

initMyfuncs_t _initMyfuncs = some_function;  // actual definition of the pointer with optional initializer.

混淆来自函数 pointer 的类型定义,不同于函数 prototype。即使没有 extern 关键字,函数原型也是一个声明。

extern int a;

a声明。它(只是)对编译器的 承诺 a 将在 link 左右出现。

实际定义需要在别处完成,通常在.c文件中通过

int a = 42; /* The initialiser is optional, if missing it will default to '= 0'. */

以上概念对任何类型都是一样的。

一个头文件可以包含在很多源文件中。如果没有 extern 关键字,也会分配存储空间。如果头文件中没有 extern 关键字,则此存储空间将分配到包含头文件的每个源文件中。在 link 时间,linker 现在会抱怨多个符号(一些 linker 优雅地解决了这个问题)。

为了避免这种情况,又不必在源文件中单独声明对象,我使用了以下方法:

/* myInclude.h */
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myGlobalVar;

/* someFile.c */
#include "myInclude.h"

/* main.c */
#define EXTERN
#include "myInclude.h"

这将为 main.c 中的对象分配存储空间,并在包括头文件在内的所有其他源文件中将其声明为 extern

我想我得到了答案

1.without extern in header 会出现重定义错误,如果我们使用相同的变量 (initMyfuncs_t _initMyfuncs = nullptr;)

  1. 或者我们可以只提及 typedef 函数指针并在源文件中初始化一个变量

myfuncs.h

typedef void(*initMyfuncs_t)(int*, int*, int*);

并在源代码中初始化它 myfuncs.c

initMyfuncs_t _initMyfuncs = nullptr;     

如果我们需要在头文件中声明,那么

myfuncs.h

typedef void(*initMyfuncs_t)(int, int, int);
extern  initMyfuncs_t _initMyfuncs;

并在源文件中初始化

initMyfuncs_t _initMyfuncs = nullptr;

最后,当在任何源文件中使用此头文件时,也可以使用此变量,因为我们在其中声明了 extern