哈楼大家好啊!今天给大家讲一下在一些复杂的代码中出现的一些代码的解释他们分别是(*(void(*)(int))0)(int)与void(sigture(void(*)(int))(int))(int)。
看着是不是很头大,没关系啊下面我详细的介绍一下他们。
目录
二.void(*single(void(*)(int),int))(int)
一.(*(void(*)(int))0)(int)
首先还是从简单的说起首先我们先将这一串代码拆分一下:
首先void(*)(int)这个是不是很眼熟如果还没有看出来的话子啊看一下这个:int(*p)(int)这样的话是不是就顺眼多了没错他就是一个函数指针类型。那他外面再加一个括号是什么呢?并且后买你还加了一个‘0’.其实我们仔细回顾一下我们学过的知识他是不是很像一个强制类型转换,那么(void(*)(int))0这段代码的意思就是将0强制转化为void(*)(int)这个类型。
那括号前面的那一个*号就是解引用了,最外面括号外面还有一个(int),那这个是不是就有点咸一个函数调用了呢?
我们举一个例子相信大家肯定更容易懂
#include<stdio.h>
void print(int x)
{
printf("这个数字是%d\n", x);
}
int main()
{
void (*test)(int) = print;
test(1);
int a = test;
printf("这个函数的地址是%p\n", (void(*)(int))a);
(*(void(*)(int))a) (2);
return 0;
}
这个代码可以分为以下步骤来理解:
1.首先创建一个void(*)(int)类型的函数指针名为test,将print函数赋予test,由于函数名就代表函数的地址这可以通过test指针去调用这个函数最终打印出来的是1。
2.将test的值赋予a并将a强制转换为void(*)(int)类型并打印,这个地址就是函数print的地址,(注:由于每次打印print的地址都会该百年所以只能将test的地址赋予a,并强制转化a来解释)
3.最后来到我们要讲的这个代码首先void(*)(int)被括号括起来后面放一个a(这个a也是整形与0相仿)其实就是跟上面打印的时候相同为强制类型转换也就相当于test的地址,之后解引用并输入参数2调用。
大概就是这么个思路正如我们上面所说函数无论是他的&还是函数名都是他的地址,那是不是
前面那个*也可以去掉呢?答案是可以的,不信你们可以自己去试一下。
二.void(*single(void(*)(int),int))(int)
讲了比较简单的那个就来讲比较复杂的吧,看着这个是不是更复杂,他其实是一个函数的申明由于他不像函数调用可以执行就不去举例子了。
首先我们将这个代码拆分一下首先看signed里卖的那个void(*)(int)这个不就是上面讲的一个函数指针类型吗,后买还有一个int,我们不去想的那么复杂先将这个函数指针类型替换为“int”就变为single(int,int)这样是不是就明白了。
其实呢signed就是一个函数只不过参数是void(*)(int)而已,现在我们知道signed是一个函数名那我们就可以把他给去掉变为void(*)(int),哈哈,这不老熟人了吗?兄弟们熟不熟悉还是我们的函数指针那我们继续使用我们的老套路讲他变为“int”那这个就变为了int single(int,int)是不是逐渐明朗起来了。
现在可能有人会问了那single原本在void(*)(int)里面怎么到我这就到外面了呢?其实吧c语言规定这个类型创建时由于()的优先级要高于*所以只能用括号括起来了。那如果写成这样
void(*)(int)single(void(*)(int),int)这样是不是就明白了。
欧克了我们的介绍就到这里了,喜欢的兄弟们可以一键三连,欢迎大佬来指出错误qwq!!!
拜拜啦!