Tug*_*.44 6 c typedef function-pointers extern
我在使用typedef理解指向函数的指针的语法时遇到了问题.我已经阅读了很多答案,但仍然无法理解.我会试着解释一下我是如何看待事物的,这样你才能理解我的想法.
因此我们使用typedef为现有类型提供别名,例如:
typedef int number;
Run Code Online (Sandbox Code Playgroud)
这样我们可以使用与整数相同的数字(类似于预处理器指令 - 我知道在制作指针的typedef时会有一些差异).另一个例子 :
typedef struct
{
int num;
} MyStruct;
Run Code Online (Sandbox Code Playgroud)
将为未命名的结构提供名为MyStruct的别名.
所以这是函数typedef指针的语法:
typedef int (*pFunc)(int, int);
Run Code Online (Sandbox Code Playgroud)
也许我很难理解这一点,因为typedef就像它给TYPES赋予别名的名字而且函数不是完全类型但是无论如何,根据我的理解,这更像是指向某种函数签名的指针,所以第一个int是返回的类型,第二个括号用于指示传递给函数的参数是什么类型.现在我不太明白这一部分:
(*pFunc)
Run Code Online (Sandbox Code Playgroud)
好吧,说我是对的,通常指向一些内存的指针声明如下:
int *p;
double *p;
.
.
.
Run Code Online (Sandbox Code Playgroud)
因此,按照以下方式进行操作会更有意义:
(pFunc*)
Run Code Online (Sandbox Code Playgroud)
因为对我而言,如果星号位于名称之前,它看起来像pFunc是某种类型的类型指针的变量名,而不是实际的类型指针.
好吧,另一件困扰我的事情就是语法的顺序.到目前为止,在所有typedef定义中,我们左边是类型,右边是别名.
typedef int number;
typedef struct
{
int num;
} MyStruct;
Run Code Online (Sandbox Code Playgroud)
我们看到int和struct是左边的类型,我们给它们的别名是右边的.
现在,在指向函数typedef的指针中,它不遵循此约定.我们在右边的函数返回了类型,然后是括号中的typename,然后是括号中的参数类型,这个顺序让我在查看其他typedef如何处理相同的顺序后感到困惑.
做这样的事情会不会更有意义?:
typedef int (int,int) Func;所以我们首先得到一个typedef,我们想要给别名的类型,在这种情况下是一个函数签名,它取2个int并返回一个int,然后在右边我们有别名.它会更有意义吗?这跟随其他的typedef顺序,我只是没有得到那么多的函数指针顺序..
在typedef使用用于声明类型作为通常会被用于声明值的相同语法.
例如,如果我们声明一个int被叫myInt,我们做:
int myInt;
Run Code Online (Sandbox Code Playgroud)
如果我们要声明一个名为myIntTypeint 的类型,我们只需添加typedef:
typedef int myIntType;
Run Code Online (Sandbox Code Playgroud)
我们可以声明一个函数myFunc,如下所示:
int myFunc(int a, int b);
Run Code Online (Sandbox Code Playgroud)
这告诉编译器我们可以调用具有该名称和签名的实际函数.
我们还可以通过以下方式声明函数类型myFuncType:
typedef int myFuncType(int a, int b);
Run Code Online (Sandbox Code Playgroud)
我们可以这样做:
myFuncType myFunc;
Run Code Online (Sandbox Code Playgroud)
这相当于之前的声明myFunc(虽然很少使用这种形式).
功能不是传统值; 它表示带有入口点地址的代码块.像上面那样的函数声明是隐含的extern; 他们告诉编译器命名的东西存在于其他地方.但是,您可以获取函数的地址,该函数称为函数指针.函数指针可以指向具有正确签名的任何函数.通过在类型/值的名称前加上a来声明指针*,因此,我们可以尝试:
int *myFuncPtr(int a, int b);
Run Code Online (Sandbox Code Playgroud)
但这是不正确的,因为它*与the 绑定得更紧密int,所以我们声明这myFuncPtr是一个返回指针的函数int.我们必须在指针和名称周围放置parens以更改绑定顺序:
int (*myFuncPtr)(int a, int b);
Run Code Online (Sandbox Code Playgroud)
要声明一个类型,我们只需添加typedef到前面:
typedef int (*myFuncPtrType)(int a, int b);
Run Code Online (Sandbox Code Playgroud)
在myInt上面的声明中,编译器为变量分配了一些内存.但是,如果我们在不同的编译单元中编写一些代码并想要引用myInt,我们需要将其声明为extern(在引用编译单元中),以便引用相同的内存.如果没有extern,编译器将分配第二个myInt,这将导致链接器错误(实际上这不是真的,因为C允许暂定定义,您不应该使用).
如上所述,函数不是正常值,并且总是隐式的extern.但是,函数指针是正常值,extern如果您尝试从单独的编译单元引用全局函数指针,则需要该函数指针.
通常,您可以将extern全局变量(和函数)的s放入头文件中.然后,您可以将标头包含在包含这些变量和函数的定义的编译单元中,以便编译器可以确保类型匹配.