LinuxSir.cn,穿越时空的Linuxsir!

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

(*(void(*)())0)(). 是什么意思啊..晕了

[复制链接]
发表于 2004-12-13 13:48:03 | 显示全部楼层 |阅读模式
那本C语言陷阱与缺陷里面的
...
Armed with this knowledge, we are now prepared to tackle
(*(void(*)())0)(). We can analyze this statement in two parts.
First, suppose that we have a variable fp that contains a
function pointer and we want to call the function to which fp points. That is done this way:
(*fp)();
If fp is a pointer to a function, *fp is the function itself,
so (*fp)() is the way to invoke it. The parentheses
in (*fp) are essential because the expression would otherwise be interpreted as *(fp()).
We have now reduced the problem to that of finding
an appropriate expression to replace fp.
This problem is the second part of our analysis. If C could read our mind about types, we could write:
(*0)();
This doesn’t work because the * operator insists on having a pointer as its operand. Furthermore, the operand must be a pointer to a function so that the result of * can be called.
Thus, we need to cast 0 into a type loosely described as ‘‘pointer to function returning void.’’
If fp is a pointer to a function returning void,
then (*fp)() is a void value, and its declaration would look like this:
void (*fp)();
Thus, we could write:
void (*fp)();
(*fp)();
at the cost of declaring a dummy variable. But once we know how to declare the variable,
we know how to cast a constant to that type:
just drop the name from the variable declaration.
Thus, we cast 0 to a ‘‘pointer to function returning void’’
by saying:

(void(*)())0
and we can now replace fp by (void(*)())0:
(*(void(*)())0)();
The semicolon on the end turns the expression into a statement.
At the time we tackled this problem, there was no such thing as a typedef declaration. Using it,
we could have solved the problem more clearly:
typedef void (*funcptr)();
(* (funcptr) 0)();
...

看不大明白,高人指点一二,谢谢
发表于 2004-12-13 14:37:33 | 显示全部楼层
解释了如何将数字0直接转换成函数指针并调用。

...
知道了这点以后,我们现在准备好处理(*(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)();
...
 楼主| 发表于 2004-12-13 15:09:45 | 显示全部楼层
谢谢 哪里有中文版下的

最初由 bobhuang 发表
解释了如何将数字0直接转换成函数指针并调用。

...
知道了这点以后,我们现在准备好处理(*(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)();
...
发表于 2004-12-13 16:01:42 | 显示全部楼层
上面的是我刚刚自己翻的。可能有中文版下,因为以前我好像看到过类似的内容,哪里有就不清楚了。
发表于 2004-12-15 12:39:04 | 显示全部楼层
发表于 2004-12-15 12:43:15 | 显示全部楼层
好象不全
 楼主| 发表于 2004-12-15 15:08:11 | 显示全部楼层
看了一下,发现一个错误
....
这可以精确地描述C中通常将指针误以为是其指向的数据的错误。正将常会在字符串中发生。例如:

char *p, *q;
p = "xyz";

尽管认为p的值是xyz有时是有用的,但这并不是真的,理解这一点非常重要。p的值是指向一个有四个字符的数组中第0个元素的指针,这四个字符是'x'、'y'、'z'和'\0'。因此,如果我们现在执行:

q = p;

p和q会指向同一块内存。内存中的字符没有因为赋值而被复制。这种情况看起来是这样的:

要记住的是,复制一个指针并不能复制它所指向的东西。

    因此,如果之后我们执行:

q[1] = 'Y';

q所指向的内存包含字符串xYz。p也是,因为p和q指向相同的内存
...

偶觉得
q[1] = 'Y'; //试图修改常子符串"xyz"的值,会引起段错误

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

本版积分规则

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