你可以将指向一种类型的函数的指针转换为另一种类型的函数来获取额外的参数吗?

Pet*_*ete 6 c gtk

你可以转换这种类型的函数指针:

void (*one)(int a)
Run Code Online (Sandbox Code Playgroud)

对于这种类型之一:

void (*two)(int a, int b)
Run Code Online (Sandbox Code Playgroud)

然后使用已经强制转换的附加参数安全地调用指向函数?我原以为这样的事情是非法的,两种功能都必须兼容.(意思是相同的原型 - 相同的返回值,相同的参数列表.)但这正是GTK +代码的这一点似乎正在做什么(取自这里):

g_signal_connect_swapped(G_OBJECT(button), "clicked",
                         G_CALLBACK(gtk_widget_destroy), G_OBJECT(window));
Run Code Online (Sandbox Code Playgroud)

如果你查看"clicked"信号(或者只是从第一个链接查看其使用的其他示例),您将看到它的处理程序应该像这样声明:

void user_function(GtkButton *button, gpointer user_data);
Run Code Online (Sandbox Code Playgroud)

当您通过g_signal_connect_swapped()注册处理程序时,窗口小部件指针和数据指针参数按顺序交换,因此,声明应如下所示:

void user_function(gpointer user_data, GtkButton *button);
Run Code Online (Sandbox Code Playgroud)

这是问题所在.注册为回调的gtk_widget_destroy()函数原型如下:

void gtk_widget_destroy(GtkWidget *widget);
Run Code Online (Sandbox Code Playgroud)

只采取一个论点.据推测,因为数据指针(一个GtkWindow)和指向信号小部件的指针(一个GtkButton)被交换,它接收的唯一参数将是窗口指针,并且将被忽略的按钮指针将被忽略. .一些谷歌搜索已经出现了类似的例子,甚至注册了gtk_main_quit()之类的函数,它们完全没有参数.

我是否相信这是违反标准的?让GTK +开发人员找到一些合法的魔力让这一切都有效吗?

Arv*_*rve 2

C 调用约定使得调用者有责任清理堆栈上的参数。因此,如果调用者提供太多参数,也不是问题。附加参数将被忽略。

所以是的,您可以将函数指针转换为具有相同参数的另一个函数指针类型,然后使用一些参数,然后使用太多参数调用原始函数,它会起作用。

  • 事实上,我相信不存在“C 调用约定”这样的东西。C 标准没有定义它,因此由编译器和平台决定使用什么约定。但是,*大多数*编译器/平台使用您描述的调用约定。 (2认同)