c++ - 在 C++ 中通过指向其字节表示的指针修改对象有什么限制?

标签 c++ types language-lawyer undefined-behavior c++20

我对以下关于 cppreference (source) 中的类型别名的段落感到困惑:
每当尝试通过 AliasedType 类型的泛左值读取或修改 DynamicType 类型的对象的存储值时,除非满足以下任一条件,否则行为未定义:

  • AliasedType 和 DynamicType 类似。
  • AliasedType 是 DynamicType 的(可能是 cv 限定的)有符号或无符号变体。
  • 别名类型是 std::byte , char , 或 unsigned char : 这允许将任何对象的对象表示检查为字节数组。

  • 考虑我有一个大小大于 1 个字节的普通类型(例如标量)的对象。以什么方式(如果有的话),我是否可以通过指向不同类型的指针修改对象的字节表示而不调用未定义的行为?例如:
    int x = 5, y = 10;
    std::byte* x_bytes = reinterpret_cast<std::byte*>(&x);
    
    //#1: replacing the entire representation:
    std::memcpy(x_bytes, &y, sizeof(int));
    
    //#2: changing a random byte in the representation:
    x_bytes[0] = (std::byte)3;
    
    是否允许这两种操作,还是只允许 #1?
    问题是我不知道如何解释我引用的段落。这三个项目符号是“每当尝试读取或修改存储值 [...] 行为未定义”规则的异常(exception),这意味着如果其中一个项目符号适用,则允许读取和写入.但是,第三个项目符号只提到了“检查对象表示”,这意味着只读访问。
    我试图找到一个合适的标准页面来更详细地描述这个问题,但我没能找到,所以这就是我所拥有的与问题相关的全部内容。

    最佳答案

    Are both of these operations allowed


    是的。没有规定必须全部修改或不修改。允许修改单个字节。

    However, the third bullet only mentions the "examination of the object representation", which implies read-only access.


    标准规则不使用这样的措辞。这是最新草案的规则:

    [basic.lval]

    If a program attempts to access the stored value of an object through a glvalue whose type is not similar to one of the following types the behavior is undefined:

    • the dynamic type of the object,
    • a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
    • a char, unsigned char, or std​::​byte type.

    访问定义为:

    [defns.access]

    ⟨execution-time action⟩ read or modify the value of an object



    当然,从可移植性的角度来看,按索引顺序修改字节是非常可疑的,因为不同的系统以不同的顺序存储它们的字节,因此您将在不同的系统上修改具有不同重要性的字节。
    不同系统上的不同行为通常是不可取的。

    关于c++ - 在 C++ 中通过指向其字节表示的指针修改对象有什么限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67621227/

    相关文章:

    C++:将 constexpr lambda 初始化为 constexpr/非 constexpr 变量

    python - 如何检查变量是 lambda 函数

    c++ - 当涉及数组时,我们可以安全地从 C++ 调用 C API 函数吗?

    c++ - C++中整数异或的可能结果

    c++ - 具有不同指向成员指针的参数的非类型模板参数的特化是否保证是唯一的特化?

    c++ - 如何通过 GNU Autotools 链接共享库

    c++ - C/C++ 指针数组的内联强制转换(void**)

    c++ - 这个递归函数的时间复杂度是多少

    c++ - 根据大小扣除类型 C++

    haskell - 如何使用带有标志的类型系统来处理有时共享、有时独占的函数?