如何两次将指针转换为"void *"无效? [英] How can converting a pointer to `void*` twice be invalid?
问题描述
关于 zwol 的答案,我很困惑为什么
Regarding zwol's answer, I'm confused why
typedef void (*fp)(void); // any pointer-to-function type will show this effect
fp c = (void *)(void *)0; // invalid conversion in both C and C++
最后一行无效吗?对我来说,听起来就像两次将int(0)
转换为void*
一样,将指针转换为相同类型绝对是可以的,就像这样:
How is the last line invalid? To me, it sounds like converting int(0)
to void*
twice, where converting a pointer to the same type should be absolutely fine, like this:
int a, *pa = (int*)&a;
// ^^^^^^ Totally OK
推荐答案
您要问的是一个虚构的示例,目的是说明C规则的特殊情况,而无效的不是双重投票,这就是任务.
The thing you're asking about was a contrived example, meant to illustrate a corner case of the rules of C, and the thing that's invalid isn't the double cast, it's the assignment.
如果您有任何指向函数的指针类型,例如
If you have any pointer-to-function type, such as
typedef void (*fp)(void);
您可以使用任何有效的 null指针常量(例如
you can initialize variables of this type with any valid null pointer constant, e.g.
fp a = 0; // canonical null pointer constant in C
fp b = (void *)0; // another common choice
fp c = '\0'; // yes, really, this is a null pointer constant
fp d = (1-1); // and so is this
但是您不能使用指向fp
本身以外的任何特定类型的指针来初始化它们,即使该指针是空指针,并且即使所讨论的特定类型是void *
.
But you can't initialize them with a pointer to any specific type other than fp
itself, even if that pointer is a null pointer, and even if the specific type in question is void *
.
char *x = 0;
void *y = 0;
fp e = x; // invalid: no assignment conversion from `char *` to `fp`
fp f = y; // invalid: no assignment conversion from `void *` to `fp`
从我以前的答案中得出的结论让您感到困惑,
The line from my old answer that you were confused by,
fp g = (void *)(void *)0;
与上面的fp f = y
基本相同.这两个赋值的右侧都是类型为void *
的空指针,但是不是为 constant 的空指针,因此 assignment 为无效.
is essentially the same as fp f = y
above. The right-hand side of both assignments is a null pointer with type void *
, but not a null pointer constant, so the assignment is invalid.
您现在可能想知道为什么(void *)(void *)0
不是空指针常量,即使(void *)0
是空指针常量也是如此.这恰好是C标准的编写方式:空指针常量定义为任何值为0的整数常量表达式,可能在其前面将 one 强制转换为void *
.任何额外的强制转换,它不再是null指针常量(而是仍然是常量表达式). (整数常量表达式不能包含对指针类型的内部强制转换.)
You are probably now wondering why (void *)(void *)0
isn't a null pointer constant, even though (void *)0
is a null pointer constant. This is just the way the C standard happens to be written: a null pointer constant is defined as any integer constant expression with value 0, possibly with one cast to void *
in front of it. Any extra casts and it's no longer a null pointer constant (but is still a constant expression). (Integer constant expressions cannot contain internal casts to pointer types.)
在您的对比示例中
int a;
int *pa = (int *)&a;
不涉及任何空指针,也没有整数常量表达式,并且强制转换实际上是100%冗余的. &a
可以是一个常量表达式(当且仅当a
具有静态存储持续时间时),但它不是 integer 常量表达式.
no null pointers are involved, and no integer constant expressions either, and the cast really is 100% redundant. &a
could be a constant expression (if and only if a
has static storage duration), but it is not an integer constant expression.
这篇关于如何两次将指针转换为"void *"无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!