如何将指向“void *”的指针转换为无效?

时间:2017-11-23 01:54:00

标签: c pointers type-conversion language-lawyer

关于zwol's answer,我很困惑为什么

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*两次,将指针转换为相同类型应该绝对正常,如下所示:

int a, *pa = (int*)&a;
//           ^^^^^^ Totally OK

1 个答案:

答案 0 :(得分:4)

你问的问题是一个人为的例子,用来说明C规则的一个极端情况,而无效的东西不是双重演员,而是分配。

如果您有任何指针到函数类型,例如

typedef void (*fp)(void);

您可以使用任何有效的空指针常量初始化此类型的变量,例如

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 *

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`

我老回答的那句话让你感到困惑,

fp g = (void *)(void *)0;

与上面的fp f = y基本相同。两个赋值的右侧是类型为void *的空指针,但空指针常量,因此赋值无效。

您可能现在想知道为什么(void *)(void *)0不是空指针常量,即使(void *)0是空指针常量。这就是C标准恰好被写入的方式:空指针常量被定义为值为0的任何整数常量表达式,可能在其前面有一个强制转换为void *。任何额外的强制转换,它不再是空指针常量(但仍然是一个常量表达式)。 (整数常量表达式不能包含指针类型的内部强制转换。)

在你的对比例中

int a;
int *pa = (int *)&a;

不涉及空指针,也没有整数常量表达式,并且强制转换实际上是100%冗余。 &a可以是常量表达式(当且仅当a具有静态存储持续时间时),但它不是整数常量表达式。