将整数值转换为 void* 是回调中常用的范例吗?
该值被转换为指针,而不是发送指向值的实际指针。我在 GTK 程序的 GUI 界面代码中找到了这些示例。
g_signal_connect (pastebutton[pane],
"clicked",
G_CALLBACK(on_paste_button_pressed),
(void*)((long)pane<<4));
在上面的示例中,我指的是 g_signal_connect 的最后一个参数。当 GTK2 调用 on_paste_button_pressed
时,on_paste_button_pressed
将 user_data
void 指针强制转换回来,如下所示:
int pane = ((long)user_data) >> 4;
实际上,我将这个特定示例添加到代码中,但是我基于已有的内容。我添加了位移以避免有关转换的警告。该程序本身有四个窗格,其中包含相当多的小部件,复制和粘贴按钮允许您将所有值从一个窗格复制到另一个窗格。
这种将值转换为指针地址的方法是否经常使用,是否有理由不使用这种方法?
编辑:
从整数到 void 指针的转换也可以这样实现:
void* void_ptr = some_int - NULL;
Rather than sending an actual pointer to a value, the value is cast to a pointer. I found these examples in the GUI interface code of a GTK program.
g_signal_connect (pastebutton[pane],
"clicked",
G_CALLBACK(on_paste_button_pressed),
(void*)((long)pane<<4));
In the above example, I am referring to the last parameter of g_signal_connect
. When on_paste_button_pressed
is called by GTK2, on_paste_button_pressed
casts the user_data
void pointer back like so:
int pane = ((long)user_data) >> 4;
Actually, I added this particular example to the code, but I based it upon what was already there. I added the bit-shifting so as to avoid warnings about casting. The program itself has four panes containing quite a number of widgets, the copy and paste buttons allow you to copy all the values from one pane to another.
Is this way of casting a value to a pointer address often used, and are there reasons why this should not be used?
edit:
The cast from an integer to a void pointer can also be achieved like so:
void* void_ptr = some_int - NULL;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(7)
您应该使用宏 GINT_TO_POINTER() 和 GPOINTER_TO_INT() 在指针和整数之间进行转换。
是的,它确实可以在这些情况下使用。它适用于许多平台,但可能会失败,因为任意整数并不总是有效的指针值,尽管您所做的移位应该绕过这个问题。指针也可能无法容纳整数可以容纳的所有值;如果您在指针为 32 位的平台上使用 64 位 long
,就会出现这种情况,当然,由于您要移动该值,因此即使指针和整数也可能会失败大小相同。如果您想使用此技巧,您可能应该检查 sizeof (void*)
与您使用的整数类型的大小,并在运行时检查实际值(如果指针不够大) 。使这个完全可移植可能不值得,这样您就可以在需要的平台上使用实际的指针,因此要么将自己限制在可以使用此技巧的平台上,要么完全放弃该技巧。
这是来自 C-FAQ:
问:整数如何与指针相互转换?我可以暂时将整数填充到指针中,反之亦然吗?
答:从前,可以保证指针可以转换为整数(尽管人们永远不知道是否可以将 int 或 long 转换为整数)。需要),并且整数可以转换为指针,并且当转换为(足够大的)整数并再次转换回来时,指针保持不变,并且转换(以及任何映射)旨在“毫不奇怪”换句话说,整数/指针转换有一些先例和支持,但它们始终依赖于机器,因此不可移植。显式转换始终是必需的(尽管早期的编译器很少抱怨如果您忽略它们)。
ANSI/ISO C 标准为了确保 C 的广泛可实现性,削弱了那些早期的保证。指针到整数和整数到指针的转换是实现定义的(参见问题 11.33),并且不再保证指针可以在不改变的情况下转换为整数并返回。
将指针强制转换为整数,或将整数强制转换为指针,从来都不是好的做法。当您需要一个可以容纳任一类型数据的通用槽时,联合是一个更好的主意。
另请参阅问题 4.15、5.18 和 19.25。
参考文献:K&R1 Sec。 A14.4 页。 210
K&R2 段A6.6 页。 199
ISO 秒。 6.3.4
基本原理第二节3.3.4
H&S Sec. 6.2.3 页。 170,秒。 6.2.7 第 171-2 页
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
它已被使用。当它执行所需操作时,它的使用非常普遍。
不使用它的原因之一是理论上指针大小可能小于源整数大小。
不使用它的另一个原因是它允许您仅将一段整数数据传递给回调。如果将来您需要添加另一条数据(或切换到非整数),则必须找到并重写回调访问传递数据的每个位置。因此,如果您将来有可能必须扩展数据,最好创建一个
struct
(即使它只保存一个int
这次)并传递一个指向该struct
的指针。但是,如果您确定您永远不需要传递除该单个整数之外的任何内容,并且您的整数适合
void *
,那么该技术无论如何都不会被破坏。PS 迂腐地说,C 和 C++ 似乎都没有整数到 void * 到整数转换的往返保证,即它们不保证它能够工作并恢复原始整数值。
It is used. It is used quite commonly when it does what's required.
One reason not to use it is that theoretically pointer size might be smaller than the source integer size.
Another reason not to use it is that it allows you to pass only one piece of integer data to the callback. If in the future you'll need to add another piece of data (or switch to a non-integer), you'll have to locate and rewrite every single place where the callback makes access to the passed data. So, if there's a chance that you'd have to extend the data in the future, it is better to create a
struct
(even if it holds just a singleint
at this time) and pass a pointer to thatstruct
.But if you are sure that you'll never have to pass anything other than that single integer and that your integer fits into a
void *
, then this technique is not in any way broken.P.S. Pedantically speaking, neither C nor C++ appear to have the roundtrip guarantee for integer-to-void *-to-integer conversion, i.e. they don't guarantee that it will work and restore the original integral value.