批准的避免左值转换警告和错误的方法?
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 回答中找到了答案,他在其中引用了标准。但这让我更加困惑,因为我可以区分 lvalues 和 rvalues,但是 xvalues 和 prvalues 对我来说还是新的。
天真地,在我看来,该规则的存在是有原因的,因此一些规避它的方法可能也是[间接或直接]非法的。
我有几个关于左值转换的问题。用例包括以下内容。在第一种情况下,底层类型不同。在第二种情况下,限定符发生了变化。
float f;
*(static_cast<int*>(&f)) = 1;
int ptr = ...;
*(static_cast<volatile int*>(&ptr)) = NULL;
C 和 C++ 使用间接然后取消引用来规避左值转换错误是否合法?
如果转换仅更改限定符(即 static
const
或 volatile
),那么它在 C 和 C++ 中仍然合法吗?
如果它是合法的 C 和 C++,那么它是否违反其他规则,例如 GCC 的别名规则?
最后,如果它确实违反了 C 或 C++ 或其他规则,那么批准的方法是什么(可能是 memcpy
或 memmove
)?
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
类型兼容的对象(在这种情况下:int
或 unsigned 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 的编译器一样广泛地使用了该技术。 (我从个人经验中知道这一点。)
这与 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 回答中找到了答案,他在其中引用了标准。但这让我更加困惑,因为我可以区分 lvalues 和 rvalues,但是 xvalues 和 prvalues 对我来说还是新的。
天真地,在我看来,该规则的存在是有原因的,因此一些规避它的方法可能也是[间接或直接]非法的。
我有几个关于左值转换的问题。用例包括以下内容。在第一种情况下,底层类型不同。在第二种情况下,限定符发生了变化。
float f;
*(static_cast<int*>(&f)) = 1;
int ptr = ...;
*(static_cast<volatile int*>(&ptr)) = NULL;
C 和 C++ 使用间接然后取消引用来规避左值转换错误是否合法?
如果转换仅更改限定符(即 static
const
或 volatile
),那么它在 C 和 C++ 中仍然合法吗?
如果它是合法的 C 和 C++,那么它是否违反其他规则,例如 GCC 的别名规则?
最后,如果它确实违反了 C 或 C++ 或其他规则,那么批准的方法是什么(可能是 memcpy
或 memmove
)?
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
类型兼容的对象(在这种情况下:int
或 unsigned 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 的编译器一样广泛地使用了该技术。 (我从个人经验中知道这一点。)