函数的typedef是标准C语法吗?它与函数指针的typedef有什么不同?

mtb9vblg  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(131)

在C程序中,函数指针通常使用typedef声明:

typedef int (*PFN_RETURNING_INT)(int, int);

*表示这是一个指针,指向一个接受两个int参数并返回int的函数。
我在挖掘Windows SDK头文件,并在通过C预处理器运行rpcdec.h后发现了这个:

typedef void __stdcall
RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN (
      RPC_INTERFACE_GROUP IfGroup,
      void* IdleCallbackContext,
      unsigned long IsGroupIdle
    );

注意,没有*来表示“指针性”。它似乎是为一个 * 函数 * 定义了一个typedef,而不是一个指向函数的 * 指针 *。在我的印象中,函数不是C类型系统中的一等实体,所以我对如何理解typedef感到困惑。
当我用RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN类型的参数定义一个函数时,MSVC编译器很乐意接受它,并将其视为函数的 * 指针 *。
typedef是有效的C吗?我应该把typedef解释为定义一个函数的指针名吗?
编辑:我修改了一些以下程序:

#include <stdio.h>

typedef void (*PFN)(int x);
typedef void FN(int x);

void print(int x)
{
    printf("%d\n", x);
}

void doit(FN fn)
{
    fn(3);
}

void doit_p(PFN pfn)
{
    pfn(3);
}

int main ()
{
    doit(print);
    doit_p(print);
    // FN x = print;    // Uncommenting these two lines fails to compile.
    // doit(x);
    exit(0);
}

有趣的是,编译器很乐意接受这个程序,但是如果我取消注解main中的两行,它会抱怨“initialization of a function“。它让我想起了C中数组参数的行为,它“衰减”为指针。但这是贝瓦维尔故意的,还是偶然的?

bjp0bcyl

bjp0bcyl1#

.我的印象是函数在C类型系统中不是一等实体,所以我对如何理解typedef感到困惑。
typedef声明了一个类型的名称。它不声明函数或其他实体,也不传递函数或以其他方式在表达式中使用函数,因此函数是否是第一类实体并不重要:名称只是标识类型,而这并不要求类型是一级类型。
当我定义一个带有参数类型的函数时...
将参数声明为函数会自动调整为指向函数的指针声明。C 2018 6.7.6.3 8说:
如6.3.2.1所示,将参数声明为“返回 * 类型 * 的函数”应调整为“返回 * 类型 * 的函数指针"。
此外,当函数指示符用于表达式中而不是作为一元&的操作数时,它会自动转换为指向函数的指针,根据C 2018 6.3.2.1 4:

  • function designator* 是一个具有函数类型的表达式。除非它是sizeof运算符的操作数[失败,因为将sizeof应用于函数违反了约束],或者一元&运算符,否则类型为“function returning type”的函数指示符将转换为类型为“pointer to function returning type"的表达式。
cu6pst1q

cu6pst1q2#

typedef(s)引入了同义词,或者换句话说,不同类型的别名。函数有类型。所以你可以使用typedef声明来引入函数类型的别名。
这里有一个简单的例子。

#include <stdio.h>

typedef int Func( int, int );

Func f;

int f( int x, int y )
{
    return x + y;
}

int main( void )
{
    Func *fp = f;

    printf( "%d + %d = %d\n", 5, 5, fp( 5, 5 ) );
}
hiz5n14c

hiz5n14c3#

这个定义是有效的。在使用定义时,您可能必须使用*

void __stdcall my callback(
      RPC_INTERFACE_GROUP IfGroup,
      void* IdleCallbackContext,
      unsigned long IsGroupIdle
    );


RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN  *pointer_to_function = &my_callback;

相关问题