类型 T 的左值必须标识类型 T 的对象吗?如果 `p` 的类型为 `*T`,那么 `&*p` 是否需要 `p` 实际指向 `T` 类型的对象?

问题描述 投票:0回答:0

在 C++ 中,给定

ST *p
*p
产生一个左值 (expr.unary.op#1),如果静态类型
ST
是原始类型,则实际上将
*p
转换为右值 accesses读取
*p
conv.lvalbasic.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
限制更多——这些情况有更明确的规则:

  1. 访问指针有严格的要求(“严格别名”):如果静态类型
    ST
    属于特定类型列表,则实际访问只是定义的行为;此列表包括 more 比动态类型
    DT
    ;具体来说,
    ST
    可以是
    DT
    ,它的有符号/无符号变体,以及
    char
    unsigned char
    std::byte
    basic.lval#11)。
  2. 指针本身没有这样的要求:如果我们只评估指针
    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;
}

**

c++ pointers language-lawyer undefined-behavior dereference
© www.soinside.com 2019 - 2024. All rights reserved.