在 C++ 中,给定
ST *p
,*p
产生一个左值 (expr.unary.op#1),如果静态类型 ST
是原始类型,则实际上将 *p
转换为右值 accesses 和 读取*p
(conv.lval,basic.lval#11)。但是假设我们不将*p
转换为右值。我们可以评估&*p
,或者绑定对*p
的引用,等等。p
必须仍然指向一个dynamic类型DT
的对象或函数。
ST
必须以某种方式与 DT
相关吗?严格来说,规则 &*p
甚至可能需要 ST = DT
,但这是荒谬的,因为它比有关实际访问的规则更具限制性!引用expr.unary.op#1:
一元 * 运算符执行间接寻址。其操作数应为“指向 T 的指针”类型的纯右值,其中 T 是对象或函数类型。运算符产生一个 T 类型的左值,表示操作数指向的对象或函数。
因此标题问题:类型 T 的左值必须指向类型 T 的对象吗? “显然不是”,我想,但是标准在任何地方都回答这个问题吗?
我预计
&*p
必须比访问 *p
限制更少,并且可以比评估 p
限制更多——这些情况有更明确的规则:
ST
属于特定类型列表,则实际访问只是定义的行为;此列表包括 more 比动态类型 DT
;具体来说,ST
可以是 DT
,它的有符号/无符号变体,以及 char
、unsigned char
和 std::byte
(basic.lval#11)。p
本身,静态类型 ST
和动态类型 DT
不需要相关,因为从 static_cast
到任意类型的 void*
具有定义的行为如果满足对齐要求(expr.static.cast#14)。注意:根据 https://stackoverflow.com/a/21053756/53974,似乎(仅?)预计
p
指向一个对象或函数。
编辑:为具体起见,请考虑下面的功能
f
。
#include <iostream>
short* f(int *ip) { // assume `p` actually points to DT = int
void *vp = ip;
// ^^ legal, per https://eel.is/c++draft/conv.ptr#2
short* sp = static_cast<short*> (vp);
// legal, per [expr.static.cast#14]
return &*sp;
}
int main(int argc, char ** argv) {
int i = 0;
short* sp = f(&i);
void* vp = sp;
int* ip = static_cast<int*>(vp);
*ip = 1;
std::cout << "I: " << i << std::endl;
return 0;
}
**