C-如何将指针转换为“ void*”两次无效



关于 zwol 的答案,我很困惑为什么

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

您要问的事情是一个人为的例子,旨在说明C规则的角度,而无效的事物不是双层演员。

如果您有任何指针到功能类型,例如

typedef void (*fp)(void);

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

fp a = 0;          // canonical null pointer constant in C
fp b = (void *)0;  // another common choice
fp c = '';       // 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 *类型的空指针,但是不是 null指针常数,因此 sigsmentment 无效。

您现在可能想知道为什么(void *)(void *)0不是一个零指针常数,即使(void *)0是无效的指针常数。这只是C标准恰好写入的方式:空指针常数定义为任何具有值0的整数常数表达式,可能在其前面用一个施放给void *。任何额外的铸件,它不再是无效的指针常数(但仍然是恒定的表达)。(整数常数表达式不能包含指针类型的内部铸件。)

与您的对比示例

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

不涉及无效指针,也没有整数常数表达式,并且演员表确实是100%多余的。&a可能是恒定的表达式(并且仅当a具有静态存储持续时间),但它不是 integer 常数表达式。

最新更新