【问题标题】:function pointer to dynamic library in two different ways以两种不同方式指向动态库的函数指针
【发布时间】:2013-08-19 15:17:44
【问题描述】:

以下两个是相同的,但 C99 标准使从 void * 转换为未定义的函数指针。

有人可以解释第二个是如何工作的吗?有点混乱!

int (*fptr)(int);
fptr = (int (*)(int))dlsym(handle, "my_function");


int (*fptr)(int);
*(void **) (&fptr) = dlsym(handle, "my_function");

【问题讨论】:

    标签: c shared-libraries function-pointers


    【解决方案1】:

    在(第二个代码粘贴的)第一行声明了一个函数指针(我想你知道这一点)。

    现在,dlsym(3) 是一个返回 void * 的调用。

    所以第二行也可以读作:

    *((void **) (&fptr)) = dlsym(handle, "function");
    

    否则说:而不是将函数结果转换为int (*)(int),并将给定的结果影响到fptr;它将 fptr 上的指针(或将 fptr 的地址:指针上的指针)转换为void**。然后它取消引用这个指针,有效地给出 fptr(与原始指针相同,但没有int (*)(int) 类型),然后得到dlsym 调用的结果。这只是一种“欺骗”编译器使其不触发关于类型不匹配的警告/错误的方法。另请注意,即使您选择的语法只是个人喜好问题,在您发布的任何程序中使用它之前,您都应该完全理解它。

    希望对你有帮助;)

    【讨论】:

    • @OliCharlesworth:没有。
    • 唯一的区别是多出的括号,它们没有任何作用。
    • @OliCharlesworth:对。这就是为什么它们不在原始粘贴中的原因。现在我添加它们来解释发生了什么,因为问题是:“有人可以解释第二个是如何工作的吗?”。你是来投稿的还是来拖钓的?
    • 我是来为答案投票的,和其他人一样。您的回答似乎是声称 OP 的第二个 sn-p 应该有这些额外的括号。它不应该(也许它只需要重新措辞以明确你的意思......)
    • @OliCharlesworth:更好? :)
    【解决方案2】:

    区别与两者相同:

    float f = 3.14;
    int i = (int)f;
    

    float f = 3.14;
    int i = *(int*)&f;
    

    第一个是值的常规转换,在某些情况下(int float,或返回 8086 天的近指针 远指针)会导致一些转换;并且在某些情况下(函数指针和常规指针之间的一些转换)甚至无法编译。

    第二个是原始的按位复制,编译器将始终接受但会绕过任何转换,并可能导致将变量写入另一个不同大小的变量。可能非常危险,尤其是函数指针。

    【讨论】:

    【解决方案3】:

    第二个版本合法的原因在于 ISO 标准的以下部分:

    6.3.2.3 指针 1 指向 void 的指针可以转换为或从指向任何对象类型的指针转​​换。指向任何对象类型的指针可以是 转换为指向 void 并再次返回的指针;结果应 比较等于原始指针。

    (**void)&fptr 是指向对象的指针(因为 &fptr 是 指向函数的指针),因此第二个表达式中的强制转换是明确允许的上面的声明。您的第一个表达式试图将指向对象的指针(而不是指向 void 的指针,这是标准中的一种特殊情况)转换为指向函数的指针(不是对象),正如您所指出的,这是标准所不允许的。

    【讨论】:

      猜你喜欢
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 1970-01-01
      • 2017-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多