函数指针以两种不同的方式指向动态库

时间:2013-08-19 15:17:45

标签: c shared-libraries function-pointers

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

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

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


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

3 个答案:

答案 0 :(得分:3)

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

现在,dlsym(3)是一个返回void *

的调用

所以第二行也可以读作:

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

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

我希望它有所帮助;)

答案 1 :(得分:2)

与以下之间的区别相同:

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

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

第一个是值的常规转换,在某些情况下(int< - > float,或者在指针< - > far指针附近的8086天内返回)会导致一些转换;在某些情况下(函数指针和常规指针之间的某些转换)甚至不能编译。

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

答案 2 :(得分:1)

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

  

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

(**void),以及&fptr是指向对象的指针(因为& fptr是指向函数的指针的指针),所以你的第二个演员阵容表达式由上面的语句明确允许。您的第一个表达式是尝试将指向对象的指针(而不是指向void的指针,这是标准中的特殊情况)转换为指向函数的指针(对象) ),正如您所指出的那样,标准不允许这样做。