是否可以将不带参数并返回void的函数指针类型与带参数并返回值的函数一起使用?

阿维夫·科恩(Aviv Cohn)

在GTK库中,可以找到以下定义:

/**
 * GCallback:
 * 
 * The type used for callback functions in structure definitions and function 
 * signatures. This doesn't mean that all callback functions must take no 
 * parameters and return void. The required signature of a callback function 
 * is determined by the context in which is used (e.g. the signal to which it 
 * is connected). Use G_CALLBACK() to cast the callback function to a #GCallback. 
 */
typedef void  (*GCallback)              (void);

假定这是不带参数且不返回的void函数指针的typedef

但是,在GTK站点的Hello World示例中,显示了以下代码:

g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

其中activate有一个返回void带有两个参数的函数。G_CALLBACK是简单地转换为的宏GCallback)。

确实GCallback-typedef上方的注释表明:

这并不意味着所有回调函数都必须不带任何参数并返回void

该代码确实可以编译并运行。那怎么可能呢?

乔纳森·莱夫勒

C11标准的§6.3转换,更精确的是§6.3.2.3指针¶8表示:

可以将指向一种类型的函数的指针转换为指向另一种类型的函数的指针,然后再次返回。结果应等于原始指针。如果使用转换后的指针来调用其类型与引用的类型不兼容的函数,则该行为是不确定的。

GTK代码使程序员有责任将适当类型的函数指针传递给进行回调的函数。

g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

其中activate有一个返回void带有两个参数的函数。G_CALLBACK是简单地转换为的宏GCallback)。

假设两个参数为int; 它们的类型与讨论是巧合的。

extern void activate(int, int);

中的代码g_signal_connect()获取4个指针。第三个是回调;它是形式上的void (*callback)(void)

里面的代码g_signal_connect()期望使用2个整数(arg1arg2调用回调,因此需要使用:

((void (*)(int, int)callback)(arg1, arg2);

强制将“通用”类型callback转换为正确的函数指针类型-否则,它无法避免调用未定义的行为。您需要知道g_signal_connect()需要这样的指针作为回调参数,并强制转换为泛型类型,并且您必须将适当的指针传递给它。

还要记住,展现“不确定行为”的一种方法是“表现出预期,即使标准并不能保证预期”。表现出未定义行为的其他方式包括崩溃或破坏内存。


边注。

C11 §6.2.5类型¶28说:

指向的指针void应具有与指向字符类型的指针相同的表示和对齐要求。48)同样,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针应具有相同的表示和对齐要求。指向联合类型的所有指针应具有相同的表示和对齐要求。指向其他类型的指针不必具有相同的表示或对齐要求。

48)相同的表示形式和对齐要求旨在表示与函数的参数,函数的返回值和并集的成员具有互换性。

§6.3.2.3¶8的要求似乎暗示着所有指向不同函数类型的指针必须具有相同的表示和对齐要求。否则,很难保证第6.3.2.3¶8段的往返转换要求。

§6.2.5¶28的另一个结果是,您不能在指向函数类型的指针和指向对象类型的指针(例如)之间可靠地转换void *这会对诸如以下功能产生影响dlsym()很难干净地使用它们-如果启用了严格的警告级别,编译器可能会抱怨。

编译一些在函数指针和对象指针之间转换的代码(反之亦然),GCC 9.3.0具有以下功能gcc -std=c99 -O3 -Wall -pedantic -Wdeclaration-after-statement -Wold-style-definition -Wold-style-declaration -Wnested-externs -Wmissing-prototypes -Werror …

…: error: ISO C forbids conversion of function pointer to object pointer type [-Werror=pedantic]
…: error: ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]

这是一个警告,如果你没有-Werror-pedantic-errors有效的,如果你没有它忽略-pedantic-pedantic-errors有效。

请注意-pedantic(aka -Wpedantic)和之间的差异-pedantic-errors,如GCC在“请求或禁止警告的选项”下所述

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

对于流类型,是否可以自动推断以另一个函数为参数的函数的返回值?

来自分类Dev

我可以使用lambda指针数组来保存具有不同类型的参数/返回值的函数吗?

来自分类Dev

R编程:是否可以声明函数的返回值或参数类型?

来自分类Dev

带返回值的泛型函数参数的TypeScript参数类型推断?

来自分类Dev

如果Instr函数与命名参数一起使用并且返回值分配给变量,则VBA编译错误

来自分类Python

Python的打字:申报返回值的类型基于函数的参数

来自分类Dev

如何使TypeScript基于返回值识别函数的参数类型?

来自分类Dev

类型不完整的函数参数和返回值

来自分类Dev

是否可以将参数的默认值设置为函数的返回值?(TCL)

来自分类Dev

返回带参数的函数

来自分类Dev

是否可以返回带参数的函数但不调用它?

来自分类Dev

类型转换C函数的返回值是否可以接受?

来自分类Dev

如何在C ++中使用函数的参数作为指针从DLL返回值?

来自分类Dev

我可以使用DataKinds编写一个返回参数编码类型的值的函数吗?

来自分类Dev

是否可以展开可变参数(lambda)模板并将这些函数的返回值传递给另一个可变参数函数?

来自分类Dev

是否可以将函数的值返回给函数参数?js

来自分类Javascript

缓存其参数的返回值的函数

来自分类Dev

根据参数缩小函数的返回值

来自分类Dev

通过参数更改函数的返回值

来自分类Dev

索引无参数函数的返回值

来自分类Dev

JavaScript - 从匿名函数参数返回值

来自分类Dev

获取异步函数参数的返回值

来自分类Dev

Mips函数参数和返回值

来自分类Dev

是否可以在该函数的参数类型中使用该函数的返回类型?

来自分类Dev

如何使用函数返回值作为PHP中另一个函数的参数?

来自分类Dev

使用constexpr函数的返回值作为另一个函数的参数

来自分类Dev

将成员函数指针与参数包一起使用

来自分类Dev

如何将函数接口与具有返回值的回调一起使用

来自分类Dev

我可以使用返回值作为参数多次运行同一个函数吗?

Related 相关文章

  1. 1

    对于流类型,是否可以自动推断以另一个函数为参数的函数的返回值?

  2. 2

    我可以使用lambda指针数组来保存具有不同类型的参数/返回值的函数吗?

  3. 3

    R编程:是否可以声明函数的返回值或参数类型?

  4. 4

    带返回值的泛型函数参数的TypeScript参数类型推断?

  5. 5

    如果Instr函数与命名参数一起使用并且返回值分配给变量,则VBA编译错误

  6. 6

    Python的打字:申报返回值的类型基于函数的参数

  7. 7

    如何使TypeScript基于返回值识别函数的参数类型?

  8. 8

    类型不完整的函数参数和返回值

  9. 9

    是否可以将参数的默认值设置为函数的返回值?(TCL)

  10. 10

    返回带参数的函数

  11. 11

    是否可以返回带参数的函数但不调用它?

  12. 12

    类型转换C函数的返回值是否可以接受?

  13. 13

    如何在C ++中使用函数的参数作为指针从DLL返回值?

  14. 14

    我可以使用DataKinds编写一个返回参数编码类型的值的函数吗?

  15. 15

    是否可以展开可变参数(lambda)模板并将这些函数的返回值传递给另一个可变参数函数?

  16. 16

    是否可以将函数的值返回给函数参数?js

  17. 17

    缓存其参数的返回值的函数

  18. 18

    根据参数缩小函数的返回值

  19. 19

    通过参数更改函数的返回值

  20. 20

    索引无参数函数的返回值

  21. 21

    JavaScript - 从匿名函数参数返回值

  22. 22

    获取异步函数参数的返回值

  23. 23

    Mips函数参数和返回值

  24. 24

    是否可以在该函数的参数类型中使用该函数的返回类型?

  25. 25

    如何使用函数返回值作为PHP中另一个函数的参数?

  26. 26

    使用constexpr函数的返回值作为另一个函数的参数

  27. 27

    将成员函数指针与参数包一起使用

  28. 28

    如何将函数接口与具有返回值的回调一起使用

  29. 29

    我可以使用返回值作为参数多次运行同一个函数吗?

热门标签

归档