(void *)fun()与void (*fun)()
fun();
int fun(int p);
void fun(void);
void *fun();
void (*fun)();定义一个指针,该指针指向函数的的入口地址
(void *)fun();定义一个函数,返回值为指针
void (*fun)(void *);定义一个指针,该指针指向函数的入口地址,参数为一个void指针类型
(void *)fun(void *);定义一个函数,返回值为指针的函数,参数为void指针类型
void指针
指针有两个属性:指向变量/对象的地址 和长度 ,但是指针只存储地址,长度则取决于指针的类型,编译器根据指针的类型从指针指向的地址向后寻址,指针类型不同则寻址范围也不同,比如:
int*从指定地址向后寻4字节作为变量的存储单元
double*从指定地址向后寻8字节作为变量的存储单元
1.void指针是一种特别的指针
void *vp
//说它特别是因为它没有类型
//或者说这个类型不能判断出指向对象的长度
2.任何指针都可以赋值给void指针
type *p;
vp=p;
//不需转换
//只获得变量/对象地址而不获得大小
3.void指针赋值给其他类型的指针时都要进行转换
type *p=(type*)vp;
//转换类型也就是获得指向变量/对象大小
转:icoding.spaces.live/blog/cns!
4.void指针不能复引用
*vp//错误
因为void指针只知道,指向变量/对象的起始地址
而不知道指向变量/对象的大小(占几个字节)所以无法正确引用
5.void指针不能参与指针运算,除非进行转换
(type*)vp++;
//vp==vp+sizeof(type)
#include
#include
#include
using namespace std;
typedef struct tag_st
{
明解c语言char id[10];
float fa[2];
}ST;
//我在程序里面这样使用的
int main()
{
ST * P=(ST *)malloc(sizeof(ST));
strcpy(P->id,"hello!");
P->fa[0]=1.1;
P->fa[1]=2.1;
ST * Q=(ST *)malloc(sizeof(ST));
strcpy(Q->id,"world!");
Q->fa[0]=3.1;
Q->fa[1]=4.1;
void ** plink=(void **)P;
*((ST *)(plink)) = * Q; //plink要先强制转换一下,目的是为了让它先知道要覆盖的大小.
/
/P的内容竟然给Q的内容覆盖掉了.
cout<<" "<<" "<
system("PAUSE");
return 0;
}
函数指针 (*(void (*)( ) )0)( ) 解析C++
概述
在很多情况下,尤其是读别人所写代码的时候,对 C语言声明的理解能力变得非常重要,而C语言本身的凝练简约也使得C语言的声明常常会令人感到非常困惑,因此,在这里我用一篇的内容来集中阐述一下这个问题。
问题:声明与函数
有一段程序存储在起始地址为 0的一段内存上,如果我们想要调用这段程序,请问该如何去做?
答案
答案是 (*(void (*)( ) )0)( )。看起来确实令人头大,那好,让我们知难而上,从
两个不同的途径来详细分析这个问题。
答案分析:从尾到头
首先,最基本的函数声明: void function (paramList);
最基本的函数调用: function(paramList);
鉴于问题中的函数没有参数,函数调用可简化为 function();
其次,根据问题描述,可以知道 0是这个函数的入口地址,也就是说,0是一个函数的指针。使用函数指针的函数声明形式是:void (*pFunction)(),相应的调用形式是: (*pFunction)(),则问题中的函数调用可以写作:(*0)( )。
第三,大家知道,函数指针变量不能是一个常数,因此上式中的 0必须要被转化为函数指针。
我们先来研究一下,对于使用函数指针的函数:比如 void (*pFunction)( ),函数指针变量的原型是什
么?这个问题很简单,pFunction函数指针原型是( void (*)( ) ),即去掉变量名,清晰起见,整个加上()号。
所以将 0强制转换为一个返回值为void,参数为空的函数指针如下:( void (*)( ) )。
OK,结合2)和3)的分析,结果出来了,那就是:(*(void (*)( ) )0)( ) 。
答案分析:从头到尾理解答案
(void (*)( )) ,是一个返回值为void,参数为空的函数指针原型。
(void (*)( ))0,把0转变成一个返回值为void,参数为空的函数指针,指针指向的地址为0.
*(void (*)( ))0,前面加上*表示整个是一个返回值为void的函数的名字
(*(void (*)( ))0)( ),这当然就是一个函数了。
我们可以使用 typedef清晰声明如下:
typedef void (*pFun)( );
这样定义之后,pFun就是一个返回类型为void无参数的函数指针变量了。
这样函数变为 (*(pFun)0 )( );
问题:三个声明的分析
对声明进行分析,最根本的方法还是类比替换法,从那些最基本的声明上进行类比,简化,从而进行理解,下面通过分析三个例子,来具体阐述如何使用这种方法。
# 1:int* (*a[5])(int, char*);
首先看到标识符名 a,"[]"优先级大于"*",a与"[5]"先结合。所以a是一个数组,这个数组有5个元素,每一个元素都是一个指针,指针指向"(int, char*)",很明显,指向的是一个函数,这个函数参数是"int, char*",返回值是"int*"。OK,结束了一个。:)
# 2:void (*b[10]) (void (*)());
b是一个数组,这个数组有10个元素,每一个元素都是一个指针,指针指向一个函数,函数参数是"void (*)()"【注10】,返回值是"void"。完毕!
注意:这个参数又是一个指针,指向一个函数,函数参数为空,返回值是 "void"。
# 3. doube(*)() (*pa)[9];
pa是一个指针,指针指向一个数组,这个数组有9个元素,每一个元素都是"doube(*)()"
(也即一个函数指针,指向一个函数,这个函数的参数为空,返回值是"double")。
C语言中的函数指针
函数在内存中有一个物理位置,而这个位置是可以赋给一个指针的。一零点函数的地址就是该函数的入口点。因此,函数指针可被用来调用一个函数。函数的地址是用不带任何括号或参数的函数名来得到的。(这很类似于数组地址的得到方法,即,在只有数组名而无下标是就得到数组地址。)
怎样说明一个函数指针变量呢 ?
为了说明一个变量 fn_pointer 的类型是"返回值为 int 的函数指针", 你可以使用下面的说明语句:
int (*fn_pointer) ();
为了让编译器能正确地解释这句语句, *fn_pointer 必须用括号围起来。若漏了这对括号, 则:
int *fn_pointer ();
的意思完全不同了。fn_pointer 将是一个函数名, 其返回值为 int 类型的指针。
函数指针变量
在C语言中规定,一个函数总是占用一段连续的内存区, 而函数名就是该函数所占内存区的首地址。 我们可以把函数的这个首地址 ( 或称入口地址 ) 赋予一个指针变量, 使该指针变量指向该函数。然后通过指针变量就可以到并调用这个函数。 我们把这种指向函数的指针变量称为 " 函数指针变量 " 。
函数指针变量定义的一般形式为:
类型说明符 (* 指针变量名 )();
其中 " 类型说明符 " 表示被指函数的返回值的类型。 "(* 指针变量名 )" 表示 "*" 后面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。
例如: int (*pf)();
表示 pf 是一个指向函数入口的指针变量,该函数的返回值 ( 函数值 ) 是整型。
下面通过例子来说明用指针形式实现对函数调用的方法。
int max(int a,int b){
if(a>b)return a;
else return b;
}
main(){
int max(int a,int b);
int(*pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:\n");
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
printf("maxmum=%d",z);
}
从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:
1. 先定义函数指针变量,如后一程序中第 9 行 int (*pmax)(); 定义 pmax 为函数指针变量。
2. 把被调函数的入口地址 ( 函数名 ) 赋予该函数指针变量,如程序中第 11 行 pmax=max;
3. 用函数指针变量形式调用函数,如程序第 14 行 z=(*pmax)(x,y); 调用函数的一般形式为: (* 指针变量名 ) ( 实参表 ) 使用函数指针变量还应注意以下两点:
a. 函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
b. 函数调用中 "(* 指针变量名 )" 的两边
的括号不可少,其中的 * 不应该理解为求值运算,在此处它只是一种表示符号。
原文地址 blog.csdn/norbe/archive/2006/03/14/624257.aspx
函数指针void (*fun)()
void (*fun)();这是函数指针的声明,为分清层次,c++程序员喜欢这样:typedfy void (* Fun)();
这样定义的函数是和直接声明是一样的。
void f1();
void f2(int );
fun=&f1;
fun=&f2(1);
引用别人的:fun = &f1; // 也可以用:fun = f1;
fun= &f2(int); // 也可以用:fun= f2(int);
void (*fun)() = &f1; // 也可以用:void (*fun)() = f2(int);
//调用时如下:
fun(); // 或 (*fun)();
fp2(1); // 或 (*fun)(1);
函数指针与函数对象的比较:
class Add
{
public:
int sum(int a,int b)
{
return a+b;
}
};
Add sum_a;
cout<
结果是:5
int fun(int a,int b)
{
return a+b;
}
typedef (*Fun)(int a,int b);
Fun f=&fun;
cout<
结果是:5
void (*run)(void) = (void (*)(void))0x0;
这句话什么意思阿,没见过这样的阿
网友回复:定义了一个不带参数和返回值的函数指针run ,同时对它进行初始化。指向了内存的0号单元。
网友回复:run是一个指向返回值和参数都为空的函数的指针,0x0就是0,这个赋值就是将地址0强制转换为返回值和参数都为空的函数的地址赋给run。
网友回复:严重同意楼上两位
网友回复:(void (*)(void))0x0;这句看不懂
网友回复:(void (*)(void))0x0;这句看不懂
------------------------------------
进行强制转换.就好象(char *)str一样
网友回复:void (*run)(void)与void (*)(void)有什么区别呢
只是差个名称
对于类型来说本身叫什么就没必要
void (*)(void) 就是函数指针,它是个类型说明
网友回复:继续细化
void (*)(void)
(*) --我是函数指针
(void)-不需要传给我参数
void --我的返回类型为空
------------------
void (*run)(void)
(*run) --我是函数指针 ,我叫run
(void)-不需要传给我参数
void --我的返回类型为空
你可以这么看typedef void (*run)(void) 然后run a = (run)0x00; 这样总能理解了吧
void及void指针linux 2009-11-10
1.概述
许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧。
2.void的含义
void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向
任何类型的数据。
void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:
void a;
这行语句编译时会出错,提示“illegal use of type 'void'”。不过,即使void a的编译不会出错,它也没有任何实际意义。
void真正发挥的作用在于:
(1)对函数返回的限定;
(2)对函数参数的限定。
我们将在第三节对以上二点进行具体说明。
众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。
例如:
float *p1;
int *p2;
p1 = p2;
其中p1 = p2语句会编译出错,提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为:
p1 = (float *)p2;
而void *则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:
void *p1;
int *p2;
p1 = p2;
但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”。道理很简单,我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”。下面的语句编译出错:
void *p1;
int *p2;
p2 = p1;
提示“'=' : cannot convert from 'void *' to 'int *'”。
3.void的使用
下面给出void关键字的使用规则:
规则一如果函数没有返回值,那么应声明为void类型
在C语言中,凡不加返回值类型限定的函数,就会被编译器作为返回整型值处理。但是许多程序员却误以为其为void类型。例如:
add ( int a, int b )
{
return a + b;
}
int main(int argc, char* argv[])
{
printf ( "2 + 3 = %d", add ( 2, 3) );
}
程序运行的结果为输出:
2 + 3 = 5
这说明不加返回值说明的函数的确为int函数。
林锐博士《高质量C/C++编程》中提到:“C++语言有很严格的类型安全检查,不允许上述情况(指函数不加类型声明)发生”。可是编译器并不一定这么认定,譬如在Visual C++6.0中上述add函数的编译无错也无警告且运行正确,所以不能寄希望于编译器会做严格的类型检查。
因此,为了避免混乱,我们在编写C/C++程序时,对于任何函数都必须一个不漏地指定其类型。如果函数没有返回值,一定要声明为void类型。这既是程序良好可读性的需要,也是编程规范性的要求。另外,加上void类型声明后,也可以发挥代码的“自注释”作用。代码的“自注释”即代码能自己注释自己。
规则二
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论