[英]Explain void (*signal(int signo, void *(func)(int)))(int)
[英]What's the meaning of this piece of code? void (*signal(int sig, void (*func)(int)))(int);
我遇到了这段代码,完全迷失了解释它的含义。
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
第2行代码的详细解释是什么?
我知道void
和int
是类型,* func是函数的指针,括号是优先级。 但是我仍然没有把(*信号......),(int)和整个事物结合在一起。 越详细越好。
可能我已经知道这个宣言的意义/效果了。 但我不得不做一些试验来帮助我了解正在发生的事情,如下所示:
1 #include <signal.h>
2 void (*signal)(int sig, void (*func)(int));
3 void (*signal)(int); // then void (signal)(int) again.
4 //void (*signal(int sig, void (*func)(int)))(int); //break this line into two lines above
5
6 int main(){}
在上面的代码中,我将void (*signal(int sig, void (*func)(int)))(int)
分成两行。 对于第3行,我尝试了void (*signal)(int)
和void (signal)(int)
,同样的错误结果表明我试图重新声明signal
:
TestDeclaration.c:2:错误:'信号'重新声明为不同类型的符号/usr/include/signal.h:93:错误:之前'信号'的声明在这里
TestDeclaration.c:3:错误:'signal'重新声明为不同类型的符号/usr/include/signal.h:93:错误:之前'signal'的声明在这里
现在我知道两种审判都是不正确的申报方式,但为什么它们不正确呢? 为什么声明的原始方式不是重新声明?
它是一个函数的声明,它接受一个int
和一个指向函数的指针(使int
返回void)并返回一个指向函数的指针(取int
并返回void)。
解释或解释指南
您可以通过将括号中的所有内容视为单个实体进行解释,然后使用“声明跟随使用”规则向内工作。
void
(* signal(int sig,void(* func)(int)))
(int);
括号中的实体看起来像一个采用int
并返回void
的函数。
剥去外部部分:
*signal(int sig, void (*func)(int))
因此, signal
接受一些参数并返回可以被解除引用的东西(由于前导*
)以形成一个接受int
并返回void
的函数。
这意味着signal
是一个返回指向函数的指针的函数(取int
并返回void
)。
查看参数,它采用int
(即sig
)和void (*func)(int)
,它是一个指向函数的指针(取int
并返回void
)。
这是复杂的C声明如何变成的经典例子之一。
要理解此声明,通常有助于引入typedef:
typedef void (*sighandler_t)(int);
sighandler_t signal(int sig, sighandler_t func);
typedef声明一个指向函数的指针(接受一个int参数并且不返回任何内容)。 函数signal
现在可以看作是一个函数,它接受两个参数(一个int和一个指向函数的指针)并返回一个指向函数的指针。
这也可以从原始声明中获得,但需要一些练习。 通常的方法是从标识最外层实体的标识符开始( signal
是这种情况):
signal
是......
然后你向右读,直到你找到一个不匹配的右括号或声明的结尾: void (* signal
(int sig, void (*func)(int) )(int)
signal
是一个功能......返回...
现在,您可以选择首先解析参数,还是首先解析返回值。 我会先做返回值。 为此,您向后读取以找到匹配的左括号: void
( signal( / ... */ ) ) (int)void
( signal( / ... */ ) ) (int)
`signal是一个函数......返回指针...
以这种方式来回读取你会在连续的阶段得到:
`signal是一个函数...返回一个指向a的函数(函数正在......返回......)
`signal是一个函数...返回一个指针(函数取...返回void)
`signal是一个函数...返回一个指向(函数接受int并返回void)的指针
`signal是一个带有两个参数的函数:(一个int)和一个指向函数的指针,它接受一个int并返回void,然后返回一个指针(一个带有int并返回void的函数)
我多年前创建的助记符,在尝试理解复杂类型时非常有用:
Remember these rules for C declares
And precedence never will be in doubt
Start with the Suffix, Proceed with the Prefix
And read both sets from the inside, out.
当然,除非括号改变了优先顺序。
将它应用于这种情况:
void (*signal(int sig, void (*func)(int)))(int);
signal is:
[inside parentheses]
[suffix ()] a function, whose arguments are
sig, which is [prefix int] an integer, and
func, which is:
[inside parentheses]
[no suffix within these parens]
[prefix *] a pointer to
[suffix ()] a function, whose argument is
an int
[no more suffixes]
[prefix void] and which returns void
[no more prefixes]
[no more arguments]
[prefix *] And which returns a pointer to
[no more prefixes within these parens]
[suffix ()] a function, whose argument is
an int
[no more suffixes]
[prefix void] and which returns void.
通过一些练习,您将达到可以即时完成所有操作的程度:
"Signal is function, whose arguments are:
sig, an integer,
and func, a pointer to a function whose argument is an int and which returns void
... which returns a pointer to a function that takes int as an argument and returns void.
(抱歉第一次出错 - 我没有练习。)
是的,无论指针,数组和函数混合多么糟糕,那个助记符(当然除了括号外)都适用于所有C声明。
在尝试弄清楚别人的代码是如何工作的时候,这是一项真正有用的技巧......甚至可以找出你很久没见过的自己的东西。
但是,是的,处理你认为人们无法一目了然的任何事情的更好方法是使用typedef在层中构建它。 组件类型本身可能很有用,并且一次采取一个步骤可以防止人们迷失,试图弄清楚哪个括号匹配哪个。 善待接触你代码的下一个人!
如果您发现助记符很有用,请随意在其他地方引用它 - 请给我作为作者的信誉。
顺便说一句,还有“C解释器”工具,它将解析C解体并为您转换为英文描述。 Mine被称为CEX,原因显而易见,但是还有很多其他的存在,如果你不想将这种技能用于湿软件,或者如果有人向你提供的东西真的太难以让你跟踪,那么你应该找到一个。
让我们举一个如何使用这个令人讨厌的声明的例子:
void (*signal(int sig, void (*func)(int)))(int);
没有太多冗长,我们可以说“signal”是一个带有两个返回函数的参数的函数。
#include <stdio.h>
// First function that could be returned by our principal function
// Note that we can point to it using void (*f)(int)
void car_is_red(int color)
{
printf("[car_is_red] Color %d (red) is my favorite color too !\n", color);
}
// Second function that could be returned by our principal function
// Note that we can point to it using void (*f)(int)
void car_is_gray(int color)
{
printf("[car_is_gray] I don't like the color %d (gray) either !\n", color);
}
// The function taken as second parameter by our principal function
// Note that we can point to it using void (*func)(int)
void show_car_type(int mod)
{
printf("[show_car_type] Our car has the type: %d\n",mod);
}
/* Our principal function. Takes two parameters, returns a function. */
void (* show_car_attributes(int color, void (*func)(int)) )(int)
{
printf("[show_car_attributes] Our car has the color: %d\n",color); // Use the first parameter
int mod = 11; // Some local variable of our function show_car_attributes()
func(mod); // Call the function pointed by the second parameter (i.e. show_car_type() )
// Depending on color value, return the pointer to one of two functions
// Note that we do NOT use braces with function names
if (color == 1)
return car_is_red;
else
return car_is_gray;
}
//main() function
int main()
{
int color = 2; // Declare our color for the car
void (*f)(int); // Declare a pointer to a function with one parameter (int)
f = show_car_attributes(color, show_car_type); // f will take the return
// value of our principal function. Stated without braces, the
// parameter "show_car_types" is a function pointer of type
// void (*func)(int).
f(color); // Call function that was returned by show_car_attributes()
return 0;
}
让我们看看将会输出什么:
如果color = 1
[show_car_attributes] Our car has the color: 1
[show_car_type] Our car has the type: 11
[car_is_red] Color 1 (red) is my favorite color too !
如果color = 2
[show_car_attributes] Our car has the color: 2
[show_car_type] Our car has the type: 11
[car_is_gray] I don't like the color 2 (gray) either !
返回指向一个函数的指针:
并采用整数参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.