带有括号的typedef如“typedef int(f)(void)”是什么意思?它是功能原型吗?

问题描述 投票:27回答:6
typedef int (fc_name) (void);

这里fc_name是任何有效的C符号。

这与函数指针typedef有何不同?

c typedef
6个回答
34
投票

它是函数类型的typedef。目的是将它用于函数指针,但在这种情况下,使用它的语法是:

int bar(void);

fc_name* foo = bar; /* Note the * */

更新:如Jonathan Leffler's answer的评论中所述,typedef可用于声明函数。一种用途可能是声明一组回调函数:

typedef int (callback)(int, void*);

callback onFoo;
callback onBar;
callback onBaz;
callback onQux;

17
投票

第一个括号是多余的 - 它相当于:

typedef int fc_name(void);

我不认为这有用,但我不能让GCC自己抱怨它。

这意味着fc_name是函数类型的别名,它不带参数并返回int。虽然你可以使用以下方法声明rand()函数,但它并非直接有用。

fc_name rand;

您不能在函数定义中使用typedef

函数typedef的指针如下:

typedef int (*fc_name)(void);

此代码显示没有星号的typedef不是函数指针(解决现在删除的替代答案):

static int function(void)
{
    return 0;
}

typedef int   fc_name1 (void);
typedef int  (fc_name2)(void);
typedef int (*fc_name3)(void);

fc_name1 x = function;
fc_name2 y = function;
fc_name3 z = function;

编译时,'gcc'说:

gcc -Wextra -Wall -pedantic -c -O x.c
x.c:10:1: error: function ‘x’ is initialized like a variable
x.c:11:1: error: function ‘y’ is initialized like a variable

这段代码证明你确实可以使用fc_name *var = funcname;建议的jamesdlin

static int function(void)
{
    return 0;
}

typedef int   fc_name1 (void);
typedef int  (fc_name2)(void);
typedef int (*fc_name3)(void);

fc_name1  x_0 = function;
fc_name1 *x_1 = function;
fc_name2  y_0 = function;    // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function;    // Damn Bessel functions - and no <math.h>
fc_name3  z   = function;

使用y0,y1生成GCC警告:

x.c:12:11: warning: conflicting types for built-in function ‘y0’
x.c:13:11: warning: built-in function ‘y1’ declared as non-function

并且,基于schot的评论:

static int function(void)
{
    return 0;
}

typedef int   fc_name1 (void);
typedef int  (fc_name2)(void);
typedef int (*fc_name3)(void);

fc_name1  x_0 = function;   // Error
fc_name1 *x_1 = function;   // x_1 is a pointer to function
fc_name1  x_2;              // Declare int x_2(void);
fc_name1 *x_3 = x_2;        // Declare x_3 initialized with x_2

fc_name2  y_0 = function;   // Damn Bessel functions - and no <math.h>
fc_name2 *y_1 = function;   // Damn Bessel functions - and no <math.h>
fc_name1  y_2;              // Declare int y_2(void);
fc_name1 *y_3 = x_2;        // Declare y_3 initialized with y_2

fc_name3  z   = function;

有趣的是 - C的黑暗角落确实是黑暗的。


1
投票

有趣! typedef声明是一个声明,其中typedef作为存储类。

typedef int   fc_name1 (void);   
// this defines a function type called fc_name1 
// which takes no parameter and returns int

稍后,您可以定义如下的函数,

fc_name1 myFunc;
// this is equivalent to the next line
// int myFunc(void);

您应该能够从c / c ++标准中找到答案!


1
投票

我以前从未见过对typedef名称的这种做法,但围绕函数名称的括号对于防止它被扩展为同名的函数式宏是有用的。例如,isxxx中的ctype.h函数被定义为函数和宏。这样你就可以指向isalpha。但是C库如何定义外线isalpha?可能是这样的:

#include <ctype.h>

int
(isalpha)(int c)
{
    return isalpha(c);
}

在函数体中使用isalpha作为宏扩展,在函数头中的使用不是。


0
投票

正确的形式是:

typedef int (*myfunc)(void);

您可以定义如下函数:

int helloword(void) {
    printf("hello, world\n");
}

然后定义此函数的变量点:

myfunc hw_func;
hw_func = helloworld;

并通过函数指针调用该函数:

int ret = (*hw_func)();

我们需要函数指针的原因是C语言没有预定义的函数指针,并且使用void *指针调用函数在C语言中是非法的。


0
投票
  1 #include <stdio.h>
  2 
  3 
  4 typedef int (fc_name)(void);
  5 
  6 
  7 
  8 int test_func1 ()
  9 {
 10     printf("\n test_func1 called\n");
 11 
 12     return 0;
 13 }
 14 
 15 int test_func2 (void)
 16 {
 17     printf("\n test_func2 called\n");
 18     return 0;
 19 }
 20 
 21 int handler_func(fc_name *fptr)
 22 {
 23     //Call the actual function
 24     fptr();
 25 }
 26 
 27 int main(void)
 28 {
 29     fc_name  *f1, *f2;
 30 
 31     f1 = test_func1;
 32     f2 = test_func2;
 33 
 34     handler_func(f1);
 35     handler_func(f2);
 36 
 37     printf("\n test complete\n");
 38 
 39     return 0;
 40 }

输出: -

 test_func1 called

 test_func2 called

 test complete

所以我质疑的typedef,(这里的第4行)表示一个函数类型,与函数指针typedef不同。这种typedef没有多大意义。这些用作样式标准或只是故意创建混淆;-)

© www.soinside.com 2019 - 2024. All rights reserved.