关于 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 常数表达式。