最近我问了关于GLib代码中的一个问题,这是一个用C语言编写的GNOME项目的核心库。有人告诉我整个slots'n'signals框架都依赖于它。
在代码中,有许多从类型(1)到类型(2)的强制转换实例:
typedef int (*CompareFunc) (const void *a,
const void *b)
typedef int (*CompareDataFunc) (const void *b,
const void *b,
void *user_data)
经常会像这样链接调用:
int stuff_equal (GStuff *a,
GStuff *b,
CompareFunc compare_func)
{
return stuff_equal_with_data(a, b, (CompareDataFunc) compare_func, NULL);
}
int stuff_equal_with_data (GStuff *a,
GStuff *b,
CompareDataFunc compare_func,
void *user_data)
{
int result;
result = compare_func (data1, data2, user_data);
return result;
}
在g_array_sort()
中你可以自己看到:http://git.gnome.org/browse/glib/tree/glib/garray.c
以上回答都很详细并且可能是正确的 - 如果您身处标准委员会。Adam和Johannes应该得到他们的好研究回答的积极评价。但是,在实际工作中,您会发现此代码完全正常运行。争议吗?是的。考虑这一点:GLib可以在许多平台(Linux / Solaris / Windows / OS X)上编译/工作/测试,并使用各种编译器/链接器/内核加载程序(GCC / CLang / MSVC)。我猜标准已经无关紧要了。
我花了一些时间思考这些答案。这是我的结论:
- 如果您正在编写回调库,那么这可能没问题。Caveat emptor-自负风险。
- 否则,请不要这样做。
在撰写此响应后深入思考,我不会惊讶,如果C编译器的代码也使用相同的技巧。由于(大多数/全部?)现代C编译器都是自引导的,这意味着这个技巧是安全的。
一个更重要的研究问题:有人能找到这个技巧不起作用的平台/编译器/链接器/加载程序吗?对于这一点将获得重要的加分。我相信有一些嵌入式处理器/系统不喜欢它。但是,对于桌面计算机(以及可能的移动/平板电脑),这个技巧可能仍然有效。
void (*func)(void *)
的意思是,func
是一个指向函数的指针,其类型签名类似于void foo(void *arg)
。所以,你说得对。 - mk12