该标准不允许在指向函数的指针void *
和指向函数的指针之间进行转换:
6.3.2.3:8 指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应与原始指针比较。如果转换后的指针用于调用类型与指向的类型不兼容的函数,则行为未定义。
glib/gtk 中有几个函数打破了这个规则,一个例子是g_signal_handlers_block_by_func
在 a 中转换为大写的典型示例GtkEntry
:
void
insert_text_handler (GtkEditable *editable,
const gchar *text,
gint length,
gint *position,
gpointer data)
{
gchar *result = g_utf8_strup (text, length);
g_signal_handlers_block_by_func (editable,
(gpointer) insert_text_handler, data);
gtk_editable_insert_text (editable, result, length, position);
g_signal_handlers_unblock_by_func (editable,
(gpointer) insert_text_handler, data);
g_signal_stop_emission_by_name (editable, "insert_text");
g_free (result);
}
gpointer
是一个typedef
forvoid *
并g_signal_handlers_unblock_by_func
使用gpointer
:
guint g_signal_handlers_block_matched(gpointer instance,
GSignalMatchType mask,
guint signal_id,
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data);
#define g_signal_handlers_block_by_func(instance, func, data) \
g_signal_handlers_block_matched((instance), \
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), \
0, 0, NULL, (func), (data))
因此,使用编译此代码-std=c99
会给出以下警告:
src/client/gui.c: In function ‘insert_text_handler’:
src/client/gui.c:474:45: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
g_signal_handlers_block_by_func(editable, (gpointer)insert_text_handler, data);
我能找到使编译器静音的唯一方法是使用__extension__
:
__extension__ g_signal_handlers_block_by_func (editable, (gpointer)insert_text_handler, data);
抱歉这么长的序言,但正如您所见,glib / gtk 正在使用 gcc 扩展,并且无法在-pedantic
模式下(没有警告)编译gtk
使用信号处理程序的程序。
我的问题是:
我们可以-std=c99
结合使用__extension__
还是被迫使用-std=gnu99
?
换句话说,是否__extension__
暗示(强制)使用扩展进行编译,或者只是一条使编译器静音的指令,并且我的程序正在未定义的行为下工作?