当应用间接时,标准是否要求指针变量的左值到右值的转换? [英] Does the standard mandate an lvalue-to-rvalue conversion of the pointer variable when applying indirection?

查看:311
本文介绍了当应用间接时,标准是否要求指针变量的左值到右值的转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR

给定以下代码:

int* ptr;
*ptr = 0;

* ptr 应用间接引用之前, ptr 的左值到右值转换?

does *ptr require an lvalue-to-rvalue conversion of ptr before applying indirection?

在许多地方,但似乎没有指定足够的信息来确定 *运算符是否需要这样的转换。

The standard covers the topic of lvalue-to-rvalue in many places but does not seem to specify enough information to determine whether the * operator require such a conversion.

详细

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf =nofollow> N3485 在部分4.1 段落 1 ,并说(强调我的进展):

The lvalue-to-rvalue conversion is covered in N3485 in section 4.1 Lvalue-to-rvalue conversion paragraph 1 and says (emphasis mine going forward):


非函数非数组类型T的glvalue(3.10)可以将
转换为prvalue.53如果T是不完整类型,一个程序,
需要这种转换是错误的。如果
glvalue引用的对象不是类型T的对象,并且不是从T派生的
类型的对象,或者如果对象未初始化,程序$ b $ [...]

A glvalue (3.10) of a non-function, non-array type T can be converted to a prvalue.53 If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior.[...]

因此 *

So does *ptr = 0; necessitate this conversion?

如果我们进入 4

If we go to section 4 paragraph 1 it says:


[...]应用于表达式
(如果需要)将其转换为所需的目标类型。

[...]A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.

那么什么时候需要?如果我们来看 5 表达式,则 9值中提到 lvalue-to-rvalue / em>其中:

So when is it necessary? If we look at section 5 Expressions the lvalue-to-rvalue conversion is mentioned in paragraph 9 which says:


每当glvalue表达式作为运算符的操作数出现时,期望该操作数的prvalue ,应用左值到值(4.1),
数组到指针(4.2)或函数到指针(4.3)标准
转换将表达式转换为prvalue。 [...]

Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are applied to convert the expression to a prvalue. [...]

和段落 11


在某些上下文中,只有其副作用才会出现一个表达式。
这样的表达式被称为丢弃值表达式[...]当
表达式是一个左值时,应用
左值到右值转换(4.1) ... ...

In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression.[...] The lvalue-to-rvalue conversion (4.1) is applied if and only if the expression is an lvalue of volatile-qualified type and it is one of the following [...]

这两个段落似乎都不适用于这个代码示例和 5.3.1 一元运算符表示:

neither paragraph seems to apply to this code sample and 5.3.1 Unary operators paragraph 1 it says:


unary *操作符执行间接:应用
的表达式应该是指向对象类型的指针,或者指向
函数类型的指针并且结果是引用表达式指向的对象或
函数的左值。如果表达式
的类型是指向T的指针,则结果的类型是T。[注意:通过指向不完整类型的指针(除cv void之外),间接
是有效的。
这样获得的左值可以以有限的方式使用(例如初始化
引用);这个左值不能转换为
prvalue,参见4.1。 -end note]

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is "pointer to T," the type of the result is "T." [ Note: indirection through a pointer to an incomplete type (other than cv void) is valid. The lvalue thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to a prvalue, see 4.1. —end note ]

似乎不需要指针的

我已经看到一个答案和其他问题的意见,声称未初始化的指针的使用是未定义的行为,因为需要<$ c>价值到价值转换 ptr 之前应用间接。例如: C ++标准说解除引用一个未初始化的指针是未定义的行为?使这个参数,我不能调整的参数与最近的草案版本的标准。因为我已经看过这几次,我想澄清。

I have seen an answer and comments in other questions that claim the use of an uninitialized pointer is undefined behavior due the need for an lvalue-to-rvalue conversion of ptr before applying indirection. For example: Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior? makes this argument and I can not reconcile the argument with what is laid out in any of the recent draft versions of the standard. Since I have seen this several times I wanted to get clarification.

未定义的行为的实际证据并不重要,因为我在上面的链接问题中指出,我们有其他方法来获得未定义的行为。

The actual proof of undefined behavior is not as important since as I noted in the linked question above we have others way to get to undefined behavior.

推荐答案

我已经将我的问题中的更新部分转换为一个答案,因为这一点似乎是答案,虽然不令人满意的一个,我的问题是unanswerable:

I have converted the update section in my question to an answer since at this point it seems to be the answer, albeit an unsatisfactory one that my question is unanswerable:

dyp 指向我两个相关主题包含非常相似的地面:

dyp pointed me to two relevant threads that cover very similar ground:

一致似乎是标准是因此无法提供我正在寻找的答案, Joseph Mansfield 发布了关于缺少规范的缺陷报告,它看起来仍然是打开,目前尚不清楚何时可能

The consensus seems to be that the standard is ill-specified and therefore can not provide the answer I am looking for, Joseph Mansfield posted a defect report on this lack of specification, and it looks like it is still open and it is not clear when it may be clarified.

对于标准的 intent ,有一些常见的参数。可以参考逻辑上,如果操作需要使用该操作数的值,则操作数为prvalue。另一个论点是,如果我们回顾 C99标准草案默认值为右值转换的左值,并注明异常。 C99标准草案的相关部分为 6.3.2.1 Lvalues,数组和函数指示符

There are a few common sense arguments to be made as to the intent of the standard. One can argue Logicially, an operand is a prvalue if the operation requires using the value of that operand. Another argument is that if we look back to the C99 draft standard says an lvalue to rvalue conversion is done by default and the exceptions are noted. The relevant section from the draft C99 standard is 6.3.2.1 Lvalues, arrays, and function designators paragraph 2 which says:


除非是sizeof运算符的操作数,否则unary&运算符,++运算符,-运算符或左操作数。运算符或赋值运算符
没有数组类型的左值将转换为存储在指定对象中的值(并且不再是左值)。 [...]

Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue). […]

它基本上说有一些例外,操作数转换为存储的值<如果这在 C ++ 中也是这样,那么它将确实使我的问题的答案,这不是一个例外。

which basically says with some exceptions an operand is converted to the value stored and since indirection is not an exception if this is clarified to also be the case in C++ as well then it would indeed make the answer to my question yes.

因为我试图澄清未定义行为的证据比澄清是否强制执行左值到右值转换的重要性。如果我们想证明未定义的行为,我们有另外的方法。 Jerry的方法是常识性的,因为间接要求表达式是指向对象或函数的指针,而不确定的值只会意外地指向有效的对象。通常,C ++标准草案没有给出一个明确的声明,说使用一个不确定的值是不确定的,不像C99草案标准在C ++ 11和回到标准没有给出一个明确的语句使用不确定值是未定义的。异常是迭代器和扩展指针,我们确实有奇异值的概念, 24.2.1 部分告诉我们:

As I attempted to clarify the proof of undefined behavior was less important than clarifying whether a lvalue-to-rvalue conversion is mandated. If we want to prove undefined behavior we have alternate approaches. Jerry’s approach is a common sense one and in that indirection requires that the expression be a pointer to an object or function and an indeterminate value will only by accident point to a valid object. In general the draft C++ standard does not give an explicit statement to say using an indeterminate value is undefined, unlike the C99 draft standard In C++11 and back the standard does not give an explicit statement to say using an indeterminate value is undefined. The exception being iterators and by extension pointers we do have the concept of singular value and we are told in section 24.2.1 that:


<...> [...] [示例:在声明未初始化的指针x(如int * x;)之后,x必须总是假设为指针的奇异值。 -end example] [...]可引用值总是非奇异的。

[…][ Example: After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. —end example ] […] Dereferenceable values are always non-singular.

和:


无效的迭代器是一个可能是奇异的迭代器。 268

和脚注268说:


这个定义适用于指针,因为指针是迭代器。解除引用已失效的迭代器的效果未定义。

This definition applies to pointers, since pointers are iterators. The effect of dereferencing an iterator that has been invalidated is undefined.

在C ++ 1y ​​语言变化,我们有一个明确的声明使用的中间值未定义有一些狭窄的例外

这篇关于当应用间接时,标准是否要求指针变量的左值到右值的转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆