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

Posted

技术标签:

【中文标题】避免左值转换警告和错误的批准方法?【英文标题】:Approved way to avoid lvalue cast warnings and errors? 【发布时间】:2015-08-02 04:56:21 【问题描述】:

这与 JoGusto 在Casting Error: lvalue required as left operand of assignment 的回答有关。在回答中,他/她说:

但有一种情况不正确:强制转换,然后取消引用指针:

*((int *) chrPtrValue) = some_integer_expression;

我想我在 Joseph Mansfield answer from Why does an lvalue cast work? 找到了答案,他在其中引用了该标准。但这更让我感到困惑,因为我可以区分 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)?

【问题讨论】:

没有“C/C++”之类的东西,尤其是在谈到这样的细节时,请选择一个。 (它们被称为别名规则,而不是抗锯齿。) 谢谢垫。非正式地,我正在与 C 语言家族交谈。 C/C++ 更改为 C 和 C++。但我也在 Objective C 中工作,所以如果你对那里有洞察力,那也将不胜感激。 (而且我把标题改好了……我年纪越大,我转置的字符和单词就越多……) 【参考方案1】:

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

首先,C 和 C++ 是否可以像这样规避左值转换错误(间接然后取消引用)?

IDK 你所说的“规避左值转换错误”是什么意思。代码(T)x = y; 只是非法的废话(除了在C++ 中T 是左值引用的情况,正如约瑟夫曼斯菲尔德的回答所涵盖的那样)。你不规避它;您编写的代码具有合理的含义并执行您想做的事情。

代码*(T *)ptr = y; 编译。这意味着在T 对象上调用赋值运算符,该对象存储在ptr 的地址中。与C++中的(T &amp;)*ptr = y;相同,即reinterpret_cast&lt;T&amp;&gt;(*ptr) = y;

它是否违反了其他规则,例如 GCC 的抗锯齿规则?

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

那么批准的方法是什么(可能是 memcpy 或 memmove)?

你可以写:

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

我通常可以区分左值和右值,而不是 xvalues 和 prvalues。

在此示例中您无法识别哪些表达方式?

【讨论】:

“您无法识别哪些表达方式” - xvaluesprvalues。我在大学上过编译器理论课(这是我在大学里上过的最累的课)。我们有lvaluesrvalues,但没有其他类型。 (对我来说,大学是几年前的事了)。 "...这取决于该位置存储的对象..." - 完美;这是我下一个问题的延续。将类型转换为/从类型转换为 volatile 类型是否会影响使用上述技巧执行转换的能力?我想我在这里要问的是,即使使用修饰符也可以很好地定义吗? 见What are rvalues, lvalues, xvalues, glvalues, and prvalues? @jww 也许***.com/questions/2981827 与您的情况有关。这家伙发现他可以通过使用 volatile 来“欺骗” gcc 的别名优化(但它仍然是 UB) 是的,它不违反严格别名,因为允许的类型之一是“对象动态类型的 cv 限定版本”。正如我之前提到的,它可能无法解决您想要解决的任何问题。

以上是关于避免左值转换警告和错误的批准方法?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法避免警告/错误模板实例化回溯?

C 错误:需要左值作为一元“&”操作数

为啥非 const 引用必须用左值初始化?

为啥这个转换的结果不是左值?

如何防止VBS的错误提示

错误:无法使用“int [r][c]”类型的左值初始化“int *”类型的返回对象