使用 void* 参数传递整数或指针
Use a void* argument to pass integer OR a pointer
我想检测 void* 类型输入函数参数的值是整数还是指针。目前,我只传递整数(这是 Midnight Commander 来源):
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
(void*)(intptr_t)clip_id);
然而,有时我也想在同一个参数中传递一个字符串 (char *),因为扩展 API 会很困难。我知道这是错误的,但是,也许有一种完全合法的方式来获得这种效果?我的想法:
– 地址通常对齐到 4 或 8 个字节,所以我可以从 clip_id 中跳过这些值(跳过它们)然后解码该值? if (data % 8) then clip_id = decode_clip_id(data);
?
– 也许指针不能小到 10…20,一个简单的检查就足够了吗?
– 其他想法……?
这样的问题可以用包含联合和标签的结构来解决。
struct EventData {
enum { EV_IS_INT, EV_IS_PTR } type;
union {
intptr_t v_int;
void * v_ptr;
};
};
所以,你可以传递一个指向这个EventData
的指针,回调可以根据[=15=的值解码是访问v_int
还是v_ptr
].
struct EventData *ed = makeEventData (EV_IS_INT, clip_id);
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
ed);
如果事件是异步完成的,您可能需要动态创建事件,然后回调函数必须在回调完成时释放内存。
Windows 用他们的 HANDLE 和资源 ID 做了很多这样的黑客行为。
您的整数需要有定义的有效范围。超出该范围的任何东西都可能是指针。
几乎所有操作系统都保留低位内存区。您可能会假设 16 位范围 0 到 65535 不是指针。除此之外变得不确定。
如果您的代码需要可移植到嵌入式 RTOS 或独立环境中,那么您不能对指针做任何假设。
在任何情况下,您可能需要某种函数来创建值以传递到您的 void* 中,其中包含 assert
或 abort
以避免意外创建无效值。
我想检测 void* 类型输入函数参数的值是整数还是指针。目前,我只传递整数(这是 Midnight Commander 来源):
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
(void*)(intptr_t)clip_id);
然而,有时我也想在同一个参数中传递一个字符串 (char *),因为扩展 API 会很困难。我知道这是错误的,但是,也许有一种完全合法的方式来获得这种效果?我的想法:
– 地址通常对齐到 4 或 8 个字节,所以我可以从 clip_id 中跳过这些值(跳过它们)然后解码该值? if (data % 8) then clip_id = decode_clip_id(data);
?
– 也许指针不能小到 10…20,一个简单的检查就足够了吗?
– 其他想法……?
这样的问题可以用包含联合和标签的结构来解决。
struct EventData {
enum { EV_IS_INT, EV_IS_PTR } type;
union {
intptr_t v_int;
void * v_ptr;
};
};
所以,你可以传递一个指向这个EventData
的指针,回调可以根据[=15=的值解码是访问v_int
还是v_ptr
].
struct EventData *ed = makeEventData (EV_IS_INT, clip_id);
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
ed);
如果事件是异步完成的,您可能需要动态创建事件,然后回调函数必须在回调完成时释放内存。
Windows 用他们的 HANDLE 和资源 ID 做了很多这样的黑客行为。
您的整数需要有定义的有效范围。超出该范围的任何东西都可能是指针。
几乎所有操作系统都保留低位内存区。您可能会假设 16 位范围 0 到 65535 不是指针。除此之外变得不确定。
如果您的代码需要可移植到嵌入式 RTOS 或独立环境中,那么您不能对指针做任何假设。
在任何情况下,您可能需要某种函数来创建值以传递到您的 void* 中,其中包含 assert
或 abort
以避免意外创建无效值。