免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 22348 | 回复: 23
打印 上一主题 下一主题

怎么理解这个 *(void **)(&cosine) ? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-15 10:40 |只看该作者 |倒序浏览
在man dlopen中看到了个这样的*(void **)(&cosine),该如何理解呢?

       Load the math library, and print the cosine of 2.0:
              #include <stdio.h>
              #include <dlfcn.h>

              int main(int argc, char **argv) {
                  void *handle;
                  double (*cosine)(double);
                  char *error;

                  handle = dlopen ("libm.so", RTLD_LAZY);
                  if (!handle) {
                      fprintf (stderr, "%s\n", dlerror());
                      exit(1);
                  }

                  dlerror();    /* Clear any existing error */
                  *(void **) (&cosine) = dlsym(handle, "cos");
                  if ((error = dlerror()) != NULL)  {
                      fprintf (stderr, "%s\n", error);
                      exit(1);
                  }

                  printf ("%f\n", (*cosine)(2.0));
                  dlclose(handle);
                  return 0;
              }

不理解为什么不直接cosine = dlsym(handle, "cos");

dlsym的原型:  void *dlsym(void *handle, const char *symbol);

[ 本帖最后由 hahasasa 于 2008-7-15 10:43 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2008-07-15 13:32 |只看该作者
The four functions dlopen(), dlsym(), dlclose(), dlerror() implement the interface to the dynamic linking loader.
也就是说,这几个函数是为了实现动态链接loader的。为什么用*(void **) (&cosine) = dlsym(handle, "cos");
而不用cosine = dlsym(handle, "cos");?
cosine = dlsym(handle, "cos");只是实现了函数指针cosine指向了函数dlsym,因为动态链接,dlsym实际上是没有地址的,所以这是错误的。这里定义函数指针cosine,实际上它也是一个指针,指针也需要存储,所以用了&cosine来取得存储这个函数指针的地址,最后(void **)意思就是指向了这个函数指针指地址的值,那么这里的意思意思,就是要给动态链接的一个函数分配存储空间,而他的空间就是cosine这个函数指针的存储空间,相当于是一个值拷贝,而非指向同一块内存的操作。

论坛徽章:
0
3 [报告]
发表于 2008-07-15 14:22 |只看该作者
为了避免 warning 吧。
因为 dlsym 返回的是 void* 的指针。

论坛徽章:
0
4 [报告]
发表于 2008-07-15 15:27 |只看该作者
问题是,我把
*(void **) (&cosine) = dlsym(handle, "cos");
改成了
cosine = dlsym(handle, "cos");

编译运行这段示例程序,没出任何问题


我想,既然cosine是个指向(返回double值)函数的指针,它也该是void *吧?
而dlsym返回的也是void *,为什么还要转来转去?

[ 本帖最后由 hahasasa 于 2008-7-15 15:28 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2008-07-15 20:34 |只看该作者
原帖由 swordfish.cn 于 2008-7-15 14:22 发表
为了避免 warning 吧。
因为 dlsym 返回的是 void* 的指针。

你把那些强制类型转换去掉看看会不会有警告。而且即使是要消除警告,强制类型转换的信息也应该放到右边。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
6 [报告]
发表于 2008-07-15 20:36 |只看该作者
原帖由 hahasasa 于 2008-7-15 15:27 发表
问题是,我把
*(void **) (&cosine) = dlsym(handle, "cos");
改成了
cosine = dlsym(handle, "cos");

编译运行这段示例程序,没出任何问题

这样写本来就没有什么问题。

我想,既然cosine是个指向(返回double值)函数的指针,它也该是void *吧?

cosine 的类型是 double (*)(double), 也即指向返回值为 double, 有一个类型为 double 的参数的函数,是一个函数指针。不过由于 dlsym 返回值的类型是 void *, 直接向 cosine 赋值没有问题(至少是在 C 中,在 C++ 中好像不行).

[ 本帖最后由 MMMIX 于 2008-7-15 20:41 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
7 [报告]
发表于 2008-07-15 20:43 |只看该作者
原帖由 dreamice 于 2008-7-15 13:32 发表
cosine = dlsym(handle, "cos");只是实现了函数指针cosine指向了函数dlsym,因为动态链接,dlsym实际上是没有地址的,所以这是错误的。

dlsym(...) 是一个函数调用,cosine 获取的是它的返回值。由于指针变量也是变量,也有其自身的存储空间,因此直接向其赋值不会有什么问题。

[ 本帖最后由 MMMIX 于 2008-7-15 20:44 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2008-07-15 21:49 |只看该作者
原帖由 MMMIX 于 2008-7-15 20:34 发表

你把那些强制类型转换去掉看看会不会有警告。而且即使是要消除警告,强制类型转换的信息也应该放到右边。


其实是这样的:

  1. int main()
  2. {
  3.         int a, *b;
  4.         *(int **)&a = b;
  5.         a = b;
  6.         return 0;
  7. }
复制代码


在左边强制转换也是可以的。

[ 本帖最后由 swordfish.cn 于 2008-7-16 21:37 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
9 [报告]
发表于 2008-07-17 22:16 |只看该作者
原帖由 swordfish.cn 于 2008-7-15 21:49 发表


其实是这样的:

int main()
{
        int a, *b;
        *(int **)&a = b;
        a = b;
        return 0;
}


在左边强制转换也是可以的。

放在左边当然是可以的,只是这么做比较少见,而且意思也不是特别清楚。总之一句话,这么做看着很别扭。

论坛徽章:
0
10 [报告]
发表于 2008-07-18 00:07 |只看该作者
The ISO C standard does not require that pointers to functions can be cast back and forth to pointers to data. Indeed, the ISO C standard does not require that an object of type void * can hold a pointer to a function. Implementations supporting the XSI extension, however, do require that an object of type void * can hold a pointer to a function. The result of converting a pointer to a function into a pointer to another data type (except void *) is still undefined, however. Note that compilers conforming to the ISO C standard are required to generate a warning if a conversion from a void * pointer to a function pointer is attempted as in:

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

评分

参与人数 1可用积分 +9 收起 理由
MMMIX + 9 精品文章

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP