LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1071|回复: 7

有关函数指针的问题

[复制链接]
发表于 2003-8-1 02:47:37 | 显示全部楼层 |阅读模式
在使用动态链接的程序中:

  1. #include"dlfcn.h"
  2. #include<stdio.h>
  3. #include"mylib.h"
  4. #define LIB "./mylib.so"
  5. int
  6. main()
  7. {
  8.         void *dp;
  9.         void (*p)();    /*function pointer*/
  10.         dp = dlopen(LIB, RTLD_LAZY);
  11.         if (dp == NULL)
  12.         {
  13.                 fputs(dlerror(),stderr);
  14.                 exit(1);
  15.         }
  16.         p = dlsym(dp, "myprint");
  17.         (*p)();[color=red]/*我觉得这里要改成 p(); */[/color]
  18.         dlclose(dp);
  19.         return 0;
  20. }
复制代码


在这里,p是一个函数指针,而函数名也是一个指针,那么既然函数名后面是直接跟()操作符,那么函数指针后面也应该是直接跟()操作符。
就像对待数组一样,我们可以直接对指针使用[]操作。
但是在这里例子当中,无论我是使用(*p)(); 还是p();都可以编译通过,而且运行也没有问题,怎么解释?
发表于 2003-8-1 03:57:41 | 显示全部楼层
Quoting ``C: A Reference Manual'' (4th edition) by S. P. Harbison and G. L. Steele Jr., p. 147:

<QUOTE>
In ISO C and some other implementations, an expression of type ``pointer to function'' can be used in a function call without an explicit dereferencing; in that case, the call (*fp)(j,k) in the example above can be written as fp(j,k).
</QUOTE>

However, in my opnion, (*p)() looks more correct than p().  After all, p is a variable of type ``pointer to function''.
 楼主| 发表于 2003-8-1 11:06:56 | 显示全部楼层
最初由 高原之狼 发表
Quoting ``C: A Reference Manual'' (4th edition) by S. P. Harbison and G. L. Steele Jr., p. 147:

<QUOTE>
In ISO C and some other implementations, an expression of type ``pointer to function'' can be used in a function call without an explicit dereferencing; in that case, the call (*fp)(j,k) in the example above can be written as fp(j,k).
</QUOTE>

However, in my opnion, (*p)() looks more correct than p().  After all, p is a variable of type ``pointer to function''.


I don't think so.

we can take " regular pointer " as analogy.
In the following code segment:

  1. int a[] = {1, 2, 3};
  2. int * p = a;
  3. printf("%d",p[1]);[color=red]/* Note: we just use [color=blue]'p'[/color], but not [color=blue]'*p'[/color] */[/color]
复制代码

In this example, a is a const pointer, so it can be followed by the operator"[]". By  analogy, p can also be followed by the operator "[]".
So we can draw the conclusion: the operand of "[]" is "pointer".
By analogy, the oprand of "()" should be "pointer of function".
发表于 2003-8-1 12:14:31 | 显示全部楼层
void (*p)();
调用的时候可以写成p()或(*p)(),不过(*p)()比较清楚,让人看了以后明白。
函数和函数指针毕竟不一样,这个和数组和指针的区别一样,按正规方法应该写(*p)(),不过为了方便编译器对p()作了一些处理,使它和(*p)()的功能一样。
发表于 2003-8-1 12:26:54 | 显示全部楼层
I don't want to be pedantic, but since you are asking:

in ``int *p = a'', a is not a pointer, a is an array type, or more precisely, the identifier of array type variable a[].  A const pointer is defined as ``const int *a'', and ``int a[10]'' is defining an array type.  Even ``int a[]'' is an incomplete arrary type, not an pointer type.

Quoting from the same book, p. 124:

<QUOTE>
In C there is a close correspondence between types ``array of T'' and ``pointer to T''.  First, when an array identifier appears in an expression, the type of the identifier is converted from ``array of T'' to ``pointer of T'', and the value of the identifier is converted to a pointer to the first element of the array.
</QUOTE>

To make it clear that this is a conversion, try use sizeof() operator on both p and a in your example.  You will see that sizeof(p) is the size of a pointer (most probably 4) and a is the size of a three-member integer array (most probably 3 * 4 == 12).  And this is the only case that such a conversion does NOT happen.

看来你是在刚开始学 C,我不知道你用的是哪本书。我不敢说自己有多懂 C,但是书还是看过几本的。当年上课时用的教材是谭浩强的那本,现在回头看来,那本书虽然不算差,但是有些基本概念很不清楚。我推荐你找一本好的书来看。我真正开始理解 C,是看 Kernighan 和 Ritchie 的 ``The C Programming Language'' 的时候。
 楼主| 发表于 2003-8-1 13:05:40 | 显示全部楼层
我以前学的是C++,有一段时间没有看了,现在在准备高程,所以又重新开始看了。
我当时用的教材是钱能的,看过谭浩强的书,也看过<<C++大学教程>>。都是走马观花,因此这些基本概念都还不是很清楚。
你说的数组跟指针的关系我明白了。
但我还是不明白:
同样是指针,pd(实型指针), pf (函数指针)。
为什么可以pd[],却不应该pf(),而是(*pf)()这两个不是有点不一致了?
 楼主| 发表于 2003-8-1 13:24:30 | 显示全部楼层
刚刚看到一个声明
int (*p)[3[;
发现我说的这个问题应该是变量声明的原因。
我上面的例子中pd是指向数组元素类型的指针,而非指向数组的指针;
而pf却是函数指针,所以他们的形式应该是不一样的。
假设有一个指向代码类型的指针pc;那么或许引用的时候应该是pc()了。

是这样理解的吗?
发表于 2003-8-2 10:05:37 | 显示全部楼层
对类型的理解一定要清楚。
int (*p)[3];
这样的声明说明指针p的类型为int (*)[3],而
int a=3;
int *pd = &a;
这样的声明说明指针pd的类型是int*,与int (*)[3]是不一样的。如果把pd赋值给p,编译器就会提示:
cannot convert `int*' to `int (*)[3]' in assignment
那么同样的数组指针能不能互相赋值呢?我们来看看这个例子:
int (*p)[3];
int (*pa)[4];
p = pa;
同样是数组指针,只是指向的元素个数不同,但在编译时仍然通不过,提示:
cannot convert `int (*)[4]' to `int (*)[3]' in assignment
可见,声明不一样,就意味着类型不一样。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表