如何两次将指针转换为"void *"无效? [英] How can converting a pointer to `void*` twice be invalid?

查看:123
本文介绍了如何两次将指针转换为"void *"无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆