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