gpt4 book ai didi

我们可以混合使用 __extension__ 和 -std=c99 吗?

转载 作者:太空宇宙 更新时间:2023-11-04 02:29:29 25 4
gpt4 key购买 nike

标准不允许在指向 void * 的指针和指向函数的指针之间进行转换:

6.3.2.3:8 A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

在 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);
}

gpointervoid *typedef 并且 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 模式下编译(没有警告)a gtk 使用信号处理程序的程序。

我的问题是:

我们能否将 -std=c99__extension__ 结合使用,或者我们必须使用 -std=gnu99

换句话说,__extension__ 是否暗示(强制)使用扩展进行编译,或者只是一条让编译器静音并且我的程序在未定义行为下工作的指令?

最佳答案

如果您知道对象指针和函数指针在给定平台上具有相同的表示形式,您可以做的是转换为介于两者之间的整数类型。

可以在整数和所有指针类型之间进行转换 - 它不是未定义的,而只是实现定义的行为(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 语法 - 违反简单赋值的约束。

关于我们可以混合使用 __extension__ 和 -std=c99 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45689248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com