在同一个头文件中声明函数指针后使用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;)
- 或者我们可以只提及 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
在下面的代码中,是否可以解释为什么在声明函数指针之后就使用了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;)
- 或者我们可以只提及 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