文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>理解C语言的声明

理解C语言的声明

时间:2005-11-18  来源:我菜我怕谁

(*(void(*)())0)();如何理解呢...请看下文...

(*(void(*)())0)();

    这样的表达式会令C程序员心惊胆战。但是,并不需要这样,因为他们可以在一个简单的规则的帮助下很容易地构造它:以你使用的方式声明它。

    每个C变量声明都具有两个部分:一个类型和一组具有特定格式的期望用来对该类型求值的表达式。最简单的表达式就是一个变量:

float f, g;

说明表达式f和g——在求值的时候——具有类型float。由于待求值的时表达式,因此可以自由地使用圆括号:

float ((f));

这表示((f))求值为float并且因此,通过推断,f也是一个float。

    同样的逻辑用在函数和指针类型。例如:

float ff();

表示表达式ff()是一个float,因此ff是一个返回一个float的函数。类似地,

float *pf;

表示*pf是一个float并且因此pf是一个指向一个float的指针。

    这些形式的组合声明对表达式是一样的。因此,

float *g(), (*h)();

表示*g()和(*h)()都是float表达式。由于()比*绑定得更紧密,*g()和*(g())表示同样的东西:g是一个返回指float指针的函数,而h是一个指向返回float的函数的指针。

    当我们知道如何声明一个给定类型的变量以后,就能够很容易地写出一个类型的模型(cast):只要删除变量名和分号并将所有的东西包围在一对圆括号中即可。因此,由于

float *g();

声明g是一个返回float指针的函数,所以(float *())就是它的模型。

    有了这些知识的武装,我们现在可以准备解决(*(void(*)())0)()了。 我们可以将它分为两个部分进行分析。首先,假设我们有一个变量fp,它包含了一个函数指针,并且我们希望调用fp所指向的函数。可以这样写:

(*fp)();

如果fp是一个指向函数的指针,则*fp就是函数本身,因此(*fp)()是调用它的一种方法。(*fp)中的括号是必须的,否则这个表达式将会被分析为*(fp())。我们现在要找一个适当的表达式来替换fp。

    这个问题就是我们的第二步分析。如果C可以读入并理解类型,我们可以写:

(*0)();

但这样并不行,因为*运算符要求必须有一个指针作为他的操作数。另外,这个操作数必须是一个指向函数的指针,以保证*的结果可以被调用。因此,我们需要将0转换为一个可以描述“指向一个返回void的函数的指针”的类型。

    如果fp是一个指向返回void的函数的指针,则(*fp)()是一个void值,并且它的声明将会是这样的:

void (*fp)();

因此,我们需要写:

void (*fp)();
(*fp)();

来声明一个哑变量。一旦我们知道了如何声明该变量,我们也就知道了如何将一个常数转换为该类型:只要从变量的声明中去掉名字即可。因此,我们像下面这样将0转换为一个“指向返回void的函数的指针”:

(void(*)())0

接下来,我们用(void(*)())0来替换fp:

(*(void(*)())0)();

结尾处的分号用于将这个表达式转换为一个语句。

    在这里,我们就解决了这个问题时没有使用typedef声明。通过使用它,我们可以更清晰地解决这个问题:

typedef void (*funcptr)();
(*(funcptr)0)();

相关阅读 更多 +
排行榜 更多 +
别惹神枪手安卓版

别惹神枪手安卓版

冒险解谜 下载
坦克战争世界

坦克战争世界

模拟经营 下载
丛林反击战

丛林反击战

飞行射击 下载