假设我有一个接受void (*)(void*)函数指针的函数用作回调函数:
void do_stuff(void (*callback_fp)(void*), void* callback_arg);
Run Code Online (Sandbox Code Playgroud)
现在,如果我有这样的功能:
void my_callback_function(struct my_struct* arg);
Run Code Online (Sandbox Code Playgroud)
我可以安全地这样做吗?
do_stuff((void (*)(void*)) &my_callback_function, NULL);
Run Code Online (Sandbox Code Playgroud)
我已经看过这个问题并且我已经看过一些C标准,它们说你可以转换为'兼容函数指针',但我找不到'兼容函数指针'的含义.
作为C的新手,我很困惑何时投射指针实际上是好的.
据我所知,你几乎可以将任何指针类型转换为任何其他类型,编译器将允许你这样做.例如:
int a = 5;
int* intPtr = &a;
char* charPtr = (char*) intPtr;
Run Code Online (Sandbox Code Playgroud)
但是,通常这会调用未定义的行为(尽管它恰好在许多平台上运行).这说,似乎有一些例外:
void*自由地投射(?)char*自由地投射(?)(至少我在代码中看过它...).
那么指针类型之间的哪些转换在C 中不是未定义的行为?
编辑:
我试着研究C标准("6.3.2.3指针"一节,见http://c0x.coding-guidelines.com/6.3.2.3.html),但除了一点点之外,我并没有真正理解它void*.
EDIT2:
只是为了澄清:我明确地只询问"正常"指针,即不是关于函数指针.我意识到强制转换函数指针的规则是非常严格的.事实上,我已经问过:-):如果我转换函数指针,改变参数个数会发生什么
你可以转换这种类型的函数指针:
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 +开发人员找到一些合法的魔力让这一切都有效吗?