C typedef函数指针和extern关键字

C typedef函数指针和extern关键字,c,function-pointers,typedef,extern,C,Function Pointers,Typedef,Extern,我在理解使用typedef的函数指针的语法时遇到问题。我读了很多答案,但还是不明白。 我会尽力解释我是如何看待事情的,这样你就能理解我的想法 因此,我们使用typedef为现有类型提供别名,例如: typedef int number; typedef struct { int num; } MyStruct; 这样我们就可以使用一个与整数相同的数字(类似于预处理器指令-我知道有一些区别,比如在生成指针的typedef时)。 另一个例子: typedef int number; t

我在理解使用typedef的函数指针的语法时遇到问题。我读了很多答案,但还是不明白。 我会尽力解释我是如何看待事情的,这样你就能理解我的想法

因此,我们使用typedef为现有类型提供别名,例如:

typedef int number;
typedef struct
{
    int num;
} MyStruct;
这样我们就可以使用一个与整数相同的数字(类似于预处理器指令-我知道有一些区别,比如在生成指针的typedef时)。 另一个例子:

typedef int number;
typedef struct
{
    int num;
} MyStruct;
将为未命名的结构提供一个名为MyStruct的别名

下面是指向函数typedef的指针的语法:

typedef int (*pFunc)(int, int);
也许我很难理解这一点,因为typedef就像它的名字给类型赋予别名,而函数并不完全是类型,但无论如何,从我的理解来看,这更像是指向某种函数签名的指针,所以第一个int是返回的类型,第二个括号用于指示传递给函数的参数的类型。 现在我不太明白的是这一部分:

(*pFunc)
  • 我认为是这样的,我们创建了一个新类型(使用typedef) 名为pFunc,是一个指针,这是*的角色。现在我们 可以创建指向任何函数的这种类型的变量 用我们描述的签名。我说得对吗
好的,假设我是正确的,通常指向某些内存的指针声明如下:

int *p;
double *p;
.
.
.
那么,按照以下方式进行操作是否更有意义:

(pFunc*)
因为在我看来,如果星号在名称之前,它看起来像pFunc是某种类型的指针类型的变量名,而不是实际的指针类型

  • 我们能做到吗?如果是这样的话,是否常用星号 之后而不是之前?如果把它放在前面更常见,那么为什么呢 是吗?因为就像我说的,当我们定义指针类型时,我们总是 像上面的例子一样,在名字后面加上星号,为什么 确实是这样吗
  • 另一个关于这个的问题,我不太明白你在说什么 括号围绕*pFunc的作业。 我认为它们是用来表示pFunc类型的指针,如果我们不放括号,那么返回类型 签名的类型将是int*而不仅仅是int,是吗 对吗
好的,另一件让我困扰的事情是语法的顺序。 到目前为止,在所有typedef定义中,类型在左边,别名在右边

typedef int number;

typedef struct
{
    int num;
} MyStruct;
我们看到int和struct是左边的类型,我们给它们的别名在右边

typedef int number;

typedef struct
{
    int num;
} MyStruct;
现在,在指向函数typedef的指针中,它不遵循这个约定。 我们在右边有函数返回的类型,然后是括号中的typename,然后是括号中参数的类型,在查看其他typedef如何以相同的顺序工作后,这个顺序让我感到困惑

  • 做这样的事不是更有意义吗

    typedefint(int,int)Func所以我们首先有一个typedef,我们想给它一个别名,在本例中它是一个函数
    接受2个整数并返回一个整数的签名,然后在右边
    我们有别名。这不是更有意义吗?这是根据
    其他的typedef顺序,我只是不知道函数指针的顺序
    很多

  • 我的另一个问题是:当我们做一个指向函数的指针时,是什么 这真的意味着什么?我知道我们可以使用 我们的别名,但变量等指针存储在内存地址中 ? 一个函数需要存储什么
  • 最后,我读到关键字extern与 指向函数的指针,但无法理解此关键字的作用, 有人能给我解释一下它是干什么的吗

类型定义使用与通常用于声明值相同的语法来声明类型

例如,如果我们声明一个名为
myInt
int
,我们会:

int myInt;
如果要将名为
myIntType
的类型声明为int,只需添加
typedef

typedef int myIntType;
我们可以声明一个函数
myFunc
,如下所示:

int myFunc(int a, int b);
它告诉编译器有一个实际的函数,我们可以调用它的名称和签名

我们还可以通过执行以下操作来声明函数类型
myFuncType

typedef int myFuncType(int a, int b);
我们可以做到:

myFuncType myFunc;
这相当于先前的
myFunc
声明(尽管很少使用此表单)

函数不是常规值;它表示具有入口点地址的代码块。像上面那样的函数声明是隐式的
extern
;它们告诉编译器命名的东西存在于其他地方。但是,您可以获取函数的地址,该地址称为函数指针。函数指针可以指向具有正确签名的任何函数。指针是通过在类型/值的名称前面加上
*
前缀来声明的,因此,我们可以尝试:

int *myFuncPtr(int a, int b);
但是这是不正确的,因为
*
int
的绑定更紧密,所以我们声明
myFuncPtr
是一个返回指向
int
的指针的函数。我们必须在指针和名称周围放置paren以更改绑定顺序:

int (*myFuncPtr)(int a, int b);
要声明类型,只需在前面添加
typedef

typedef int (*myFuncPtrType)(int a, int b);
在上面的
myInt
声明中,编译器为变量分配了一些内存。但是,如果我们在不同的编译单元中编写一些代码,并且想要引用
myInt
,那么我们需要将其声明为
extern
(在引用编译单元中),以便引用相同的内存。如果没有
extern
,编译器将分配第二个
myInt
,这将导致链接器错误(实际上这不完全正确,因为C允许临时定义,
MyStruct  exampleStruct;
PMyStruct pExampleStrut;

pExampleStruct = &exampleStruct;
struct myTagStruct {     // create a struct declaration with the tag of myTagStruct
    int a;
    int b;
};

struct myTagStruct myStruct;      // create a variable myStruct of the struct
#define MYTAGSTRUCT  struct myTagStruct
MYTAGSTRUCT myStruct;
typedef int (*pFunc)(int a1, int b1);
a = 5 * b + 1;     // 5 times b then add 1
a = 5 * (b + 1);   // 5 times the sum of b and 1

int *pFunc(int a1, int b1);      // function prototype for function pFunc which returns a pointer to an int
int **pFunct(int a1, int b1);    // function prototype for function pFunc which returns a pointer to a pointer to an int
int (*pfunc)(int a1, int b1);    // function pointer variable for pointer to a function which returns an int
int *(*pFunc)(int a1, int b1);  // function pointer variable for pointer to a function which returns a pointer to an int
typedef  int * pInt;    // create typedef for pointer to an int
int *a;                 // create a variable that is a pointer to an int
pInt b;                 // create a variable that is a pointer to an int
typedef int (*pIntFunc)(int a1, int b1);    // create typedef for pointer to a function
int (*pFuncA)(int a1, int b1);           // create a variable pFuncA that is a pointer to a function
pIntFunc  pFuncB;                        // create a variable pFuncB that is a pointer to a function
typedef struct {
    int  (*pOpenSink) (void);
    int  (*pPrintLine) (char *aszLine);
    int  (*pCloseSink) (void);
} DeviceOpsStruct;

DeviceOpsStruct DeviceOps [] = {
   {PrinterOpen, PrinterLine, PrinterClose},
   {FileOpen, FileLine, FileClose},
   {TermOpen, TermLine, TermClose}
};

int OpenDevice (int iDev)
{
    return DeviceOps[iDev].pOpenSink();
}

int LineDevice (int iDev, char *aszLine)
{
    return DeviceOps[iDev].pPrintLine (aszLine);
}
int CloseDevice (int iDev)
{
    return DeviceOps[iDev].pCloseSink();
}
typedef int *pFunc(int, int);
typedef int *(pFunc(int, int));