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

时间:2015-06-07 13:31:06

标签: c function-pointers extern

在下面的代码中,可以解释为什么在函数指针声明后立即使用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。

4 个答案:

答案 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会有重新定义错误
  1. 或者我们可以提到typedef函数指针并初始化源文件中的变量
  2. 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