标准不允许在指向void *
的指针和指向函数的指针之间进行转换:
6.3.2.3:8指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再返回;结果应该 比较等于原始指针。如果使用转换指针 调用类型与指向不兼容的函数 类型,行为未定义。
glib / gtk中有几个函数违反了这条规则,例如g_signal_handlers_block_by_func
在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
的{{1}},而void *
使用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
程序。 / p>
我的问题是:
我们可以将-std=c99
与__extension__
结合使用,还是我们被迫使用-std=gnu99
?
换句话说,__extension__
是否意味着(强制)使用扩展进行编译,或者只是使编译器静音的指令,而我的程序是在未定义的行为下工作的?
答案 0 :(得分:2)
如果知道对象指针和函数指针在给定平台上具有相同的表示形式,则可以执行的操作是在两者之间转换为整数类型。
可以在整数和所有指针类型之间进行转换 - 它不是未定义的,而只是实现定义的行为(6.3.2.3,§4和§5)。
示例:
typedef void funcptr_t (void);
...
funcptr_t* fptr = func;
void* vptr = (void*)(uintptr_t)fptr;
这是实现定义的行为,不应生成诊断。
请注意:
void* vptr = fptr;
是无效的转化/未定义行为。void* vptr = (uintptr_t)fptr;
无效C语法 - 违反简单赋值的约束。