代码之家  ›  专栏  ›  技术社区  ›  James Morris

将整数值转换为void*是回调中常用的范例吗?

  •  1
  • James Morris  · 技术社区  · 15 年前

    该值不是向值发送实际指针,而是强制转换为指针。我在gtk程序的gui接口代码中找到了这些示例。

    g_signal_connect (pastebutton[pane],
                      "clicked",
                      G_CALLBACK(on_paste_button_pressed),
                      (void*)((long)pane<<4));
    

    在上面的例子中,我指的是 g_signal_connect . 什么时候? on_paste_button_pressed 由GTK2调用, 按下“粘贴”按钮 铸造 user_data 空指针返回如下:

    int pane = ((long)user_data) >> 4;
    

    实际上,我在代码中添加了这个特定的示例,但我是基于已经存在的示例。我添加了位偏移,以避免出现有关铸造的警告。程序本身有四个窗格,其中包含相当多的小部件,复制和粘贴按钮允许您将所有值从一个窗格复制到另一个窗格。

    这种将值转换为指针地址的方法是否经常使用,是否有不应该使用这种方法的原因?

    编辑:

    也可以实现从整数到空指针的转换,如下所示:

    void* void_ptr = some_int - NULL;
    
    7 回复  |  直到 15 年前
        1
  •  3
  •   AnT stands with Russia    15 年前

    它是 习惯于 . 它是 习惯于 当它做需要做的事情时很常见。

    不使用它的一个原因是理论上指针大小可能小于源整数大小。

    不使用它的另一个原因是它只允许向回调传递一个整型数据。如果将来需要添加另一段数据(或切换到非整数),则必须定位并重写回调访问传递数据的每个位置。因此,如果将来有机会扩展数据,最好创建 struct (即使只有一个 int 此时)并将指针传递给 结构 .

    但是如果你确定你永远不需要传递除这个整数以外的任何其他信息,并且你的整数符合 void * ,那么这项技术是不会被打破的。

    附笔。 从字面上讲,无论是C还是C++,都不存在整数到空*-to整数转换的往返保证,也就是说,它们不能保证它能工作并恢复原来的积分值。

        2
  •  3
  •   el.pescado - нет войне    15 年前

    您应该使用宏gint_to_pointer()和gpointer_to_int()在指针和整数之间进行转换。

    glib: Type Conversion Macros

        3
  •  1
  •   Tomas    15 年前

    将整数转换为指针用于逐值传递值。如果确实需要按引用参数,这是首选方法,因为编译器不需要取消对指针的引用。

    位移位是个坏主意,因为它会导致溢出。

    对于真正的可移植代码,应该使用intptr_t作为整数类型,因为它可以很好地装入指针中。

        4
  •  0
  •   JaakkoK    15 年前

    是的,在这种情况下它确实有用。它可以在许多平台上工作,但可能会失败,因为任意整数并不总是有效的指针值,尽管您所做的移位应该可以绕过这个问题。指针也有可能无法保存整数可以保存的所有值;如果使用64位 long 在一个指针是32位的平台上,当然,由于您正在转移值,即使指针和整数大小相同,它也可能失败。如果你想使用这个技巧,你应该检查一下 sizeof (void*) 根据使用的整数类型的大小,如果指针不够大,则在运行时检查实际值。可能不值得让它完全可移植,这样您就可以在需要的平台上使用实际的指针,所以要么将自己限制在这个技巧有效的平台上,要么完全放弃这个技巧。

        5
  •  0
  •   Michael Krelin - hacker    15 年前

    我觉得很好。没有使用频率的统计数据,但你真的在乎吗?

    不过,我不知道比特移位有多大帮助。

        6
  •  0
  •   paxdiablo    15 年前

    它是用过的,但绝对不能携带,所以你必须小心。

    C标准并不要求指针类型至少有整数类型那么多的位,因此您可能并不总是能够做到这一点。

    但我想不起来了 任何 指针所处的平台 事实上 小于整数,所以您可能是安全的(尽管技术上不安全)。

    我认为铸件可能存在的唯一原因是消除了对准警告的可能性。C1X草案第6.3.2.3节规定:

    整数可以转换为任何指针类型。除非之前指定,否则 结果是实现定义的,可能未正确对齐,可能未指向 引用类型的实体,可能是陷阱表示形式。

        7
  •  0
  •   Robert S. Barnes Antoni    15 年前

    这来自C-FAQ:

    问: How are integers converted to and from pointers? Can I temporarily stuff an integer into a pointer, or vice versa?

    答:从前,有人保证指针可以转换成整数(尽管人们永远不知道是否需要整型或长型),也有人保证整数可以转换成指针,而且指针在转换成(足够大的)整数并返回增益,并且转换(和任何映射)的目的是“对那些知道机器寻址结构的人来说并不奇怪”。换句话说,整数/指针转换有一些先例和支持,但它们始终依赖于机器,因此不可移植。显式强制转换一直都是必需的(尽管早期的编译器很少抱怨您遗漏了它们)。

    为了确保c的广泛实施,ansi/isoc标准削弱了那些早期的保证。指针到整数和整数到指针的转换是由实现定义的(请参见问题11.33),并且不再保证指针可以转换为整数并返回,而无需更改。

    将指针强制为整数,或将整数强制为指针,从来都不是好的做法。当您需要一个可以容纳这两种数据的通用槽时,联合是一个更好的主意。

    另见问题4.15、5.18和19.25。

    参考文献:K&R1秒。A14 4P 210 K&R2秒。A6 6 P 199 ISO SEC。3.3.4 基本原理3.3.4 H&S秒。6.2.3第170页,第6.2.7第171-2页

    推荐文章