批准的避免左值转换警告和错误的方法?

Approved way to avoid lvalue cast warnings and errors?

这与 JoGusto 在 Casting Error: lvalue required as left operand of assignment 的回答有关。在答案中,he/she 指出:

but there is one case where it is not true: casting, then dereferencing a pointer:

*((int *) chrPtrValue) = some_integer_expression;

我想我在 Why does an lvalue cast work? 的 Joseph Mansfield 回答中找到了答案,他在其中引用了标准。但这让我更加困惑,因为我可以区分 lvaluesrvalues,但是 xvaluesprvalues 对我来说还是新的。

天真地,在我看来,该规则的存在是有原因的,因此一些规避它的方法可能也是[间接或直接]非法的。

我有几个关于左值转换的问题。用例包括以下内容。在第一种情况下,底层类型不同。在第二种情况下,限定符发生了变化。

float f;
*(static_cast<int*>(&f)) = 1;

int ptr = ...;
*(static_cast<volatile int*>(&ptr)) = NULL; 

C 和 C++ 使用间接然后取消引用来规避左值转换错误是否合法?

如果转换仅更改限定符(即 static constvolatile),那么它在 C 和 C++ 中仍然合法吗?

如果它是合法的 C 和 C++,那么它是否违反其他规则,例如 GCC 的别名规则?

最后,如果它确实违反了 C 或 C++ 或其他规则,那么批准的方法是什么(可能是 memcpymemmove)?

JoGusto 的答案是 (a) 不太好,并且 (b) 在 C 题上。

First, is it legal C and C++ circumvent the lvalue cast error like that (indirection then dereferencing)?

我不知道你所说的 "circumvent the lvalue cast error" 是什么意思。代码 (T)x = y; 只是非法的废话(C++ 中 T 是左值引用的情况除外,正​​如 Joseph Mansfield 的回答所涵盖的那样)。你不规避它;您编写的代码具有合理的含义并且可以做您想做的事情。

代码*(T *)ptr = y;编译。它意味着对存储在 ptr 中地址的 T 对象调用赋值运算符。和C++中的(T &)*ptr = y;是一样的,就是reinterpret_cast<T&>(*ptr) = y;.

does it violate other rules, like GCC's anti-aliasing rules?

该行为受对齐和严格别名限制。如果实际上没有 T 对象存储在该地址,也没有根据严格别名规则中的列表与 T 类型兼容的对象(在这种情况下:intunsigned int), 那么它是未定义的行为。

then what is the approved way to do it (perhaps a memcpy or memmove)?

你可以这样写:

int x = some_integer_expression;
memcpy(chrPtrValue, &x, sizeof x);

I can usually differentiate between lvalues and rvalues, and not xvalues and prvalues.

在此示例中,您难以识别哪些表达式?

“左值”转换 is/was 一直用于编写编译器,直到 2010 年左右。这种非常有用的构造的丢失意味着许多遗留编译器(例如 pcom)在许多环境中不再编译。

byacc 的旧版本——可能晚至 1996 年——实际上鼓励使用这种技术。如果我没记错的话,pcom 中的代码和几个基于 pcc2 的编译器一样广泛地使用了该技术。 (我从个人经验中知道这一点。)