在下面的代码中,可以解释为什么在函数指针声明后立即使用extern。
myfuncs.h
void *glbfuncs=NULL
glbfuncs = dlopen("glbfuncs.so",RTLD_NOW);
initMyfuncs_t _initMyfuncs=NULL;
_initMyfuncs = dlsym(glbfuncs, "_initMyfuncs");
我们在myfunc.c文件中使用它
class Keys():
def __init__(self):
self.key_list = {1:"one", 2:"two", 3:"three"}
def get_name(self, key):
self.ddd = key
key1 = Keys
key1.get_name(1)
通常,我们在文件或其他头文件中使用extern,我们使用此函数指针或变量。 这里我们在头文件中声明了extern并在同一个源文件中使用它。 在这里使用extern有什么用?
此函数指针正在其他源文件中使用,没有extern声明。我对此感到困惑?通常,我们在某处(somehere.h)有一个声明,如果我们在其他文件(here.h或here.c)中使用它,我们使用extern关键字来获取这个变量。
我不太明白在typedef之后使用extern关键字的原因。
为什么我们在同一个头文件中声明fucntion指针后使用extern。
答案 0 :(得分:3)
需要extern
关键字来区分全局数据对象的声明,例如函数指针和此对象的定义。
在头文件中,您应该只有声明。定义属于源文件,不应在不同的源文件中重复。如果将定义放在头文件中,则在链接时最终会对相同符号进行多次定义。由于历史原因,如果没有初始化器,则常见链接器接受这些多个定义。然而,它被认为是不好的做法,应该避免。
<强> 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.
混淆来自函数指针的typedef,不同于函数 prototype 。即使没有extern
关键字,函数原型也是一个声明。
答案 1 :(得分:0)
extern int a;
是a
的声明。 (只是)编译器a
的 promise 将在链接时出现。
它的实际定义需要在其他地方完成,通常在.c
文件中通过
int a = 42; /* The initialiser is optional, if missing it will default to '= 0'. */
以上概念对于任何类型都是相同的。
答案 2 :(得分:0)
头文件可以包含在许多源文件中。如果没有extern
关键字,也会存储存储空间。如果头文件中没有extern
关键字,则会在包含头文件的每个源文件中分配此存储。在链接时,链接器现在会抱怨多个符号(一些链接器会优雅地解决这个问题)。
为了避免这种情况,我不必在源文件中单独声明对象,而是使用以下方法:
/* 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
。
答案 3 :(得分:0)
我想我得到了答案
如果我们使用相同的变量(initMyfuncs_t _initMyfuncs = nullptr;),那么在标题中没有extern会有重新定义错误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