Pointer arithmetic for pointers obtained not in this way

98 views
Skip to first unread message

Language Lawyer

unread,
May 27, 2018, 10:59:37 PM5/27/18
to std-dis...@isocpp.org
The definition of unary &, [expr.unary.op]/3 (http://eel.is/c++draft/expr.unary.op#3), says that
"For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), an object that is not an array element whose address is taken in this way is considered to belong to an array with one element of type T."
"in this way" == "using unary &"
Is it intentional that object that is not an array element whose address was not taken using unary & is not considered to belong to an array with one element (for purposes of ...)?
For example, given a pointer to a standard-layout class object and reinterpret_cast-ing it into pointer to its first member (http://eel.is/c++draft/basic.compound#def:pointer-interconvertible), the result (the pointer to the first member) won't be a pointer to an element of an array with one element for the purposes of pointer arithmetic?

struct S { int i; } s;
int* p1 = &s.i;
int* p2 = reinterpret_cast<int*>(&s);
int* p1_ = p1 + 1; // defined behaviour
int* p2_ = p2 + 1; // undefined behaviour???

Language Lawyer

unread,
May 28, 2018, 1:13:11 AM5/28/18
to ISO C++ Standard - Discussion
Even more stupid example:

int* pi = new int(0);
pi + 1; // UNDEFINED!11 Pointer was not obtained in this way!
&*pi + 1; // OK, address is taken in this way
Message has been deleted

Language Lawyer

unread,
Jul 23, 2018, 11:24:29 AM7/23/18
to std-dis...@isocpp.org
On 28/05/18 05:59, Language Lawyer wrote:
> The definition of unary &, [expr.unary.op]/3 (http://eel.is/c++draft/expr.unary.op#3), says that
> "For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), an object that is not an array element whose address is taken in this way is considered to belong to an array with one element of type T."
> "in this way" == "using unary &"
> Is it intentional that object that is not an array element whose address was not taken using unary & is not considered to belong to an array with one element (for purposes of ...)?

2 month and still no answer whether is it intentional, editorial issue or core issue...

Brian Bi

unread,
Jul 23, 2018, 11:28:56 AM7/23/18
to std-dis...@isocpp.org
See footnote to [expr.add]/4.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

Language Lawyer

unread,
Jul 23, 2018, 11:41:22 AM7/23/18
to std-dis...@isocpp.org
Footnotes are not normative. That note refers to [expr.unary.op].
And [expr.unary.op] says what I've cited in the first message.

It is a bit surprising that the language rules are so selective
about how did you get the pointer to the object which is not
an array element.
Popular belief is that any correctly obtained pointer to an object
which is not an array element is considered to be a pointer to
an element of an array of size 1 for the purposes of [expr.add].
(e.g. https://en.cppreference.com/w/cpp/language/operator_arithmetic:
"A pointer to non-array object is treated as a pointer to the first element of an array with size 1")

Bo Persson

unread,
Jul 23, 2018, 1:17:48 PM7/23/18
to std-dis...@isocpp.org
The paragraph describes the & operator, and the result of using it.
That's it.

It says nothing about what happens if you try to get the address of an
object in some other way. Possibly that is described elsewhere, where
any "other way" is described.

Generally, when the standard says "if A then B", it doesn't rule out "if
C then also B".


Bo Persson


Language Lawyer

unread,
Jul 23, 2018, 2:09:31 PM7/23/18
to std-dis...@isocpp.org
But the footnote does not refer to other subclauses in the standard. Which is, of course, not a proof, but a good indicator that "other ways" do not give a pointer which is considered as you know what.

Anyway. I've checked
http://eel.is/c++draft/expr.prim.this#:this
http://eel.is/c++draft/class.this#:this
and haven't found anything saying (either directly or indirectly) that `this` is considered to be a pointer to an array element of an array of size 1 for the purposes of pointer arithmetic if the method is called for an object which is not an array element.

This means that in the following code:
```
struct S { S* self() { return this; } };

int main()
{
S s;
S* p1 = &s;
S* p2 = s.self();
}
```
pointers p1 and p2, even though they have the same value (do they?), do seem to be different from the operator+'s POV, if we take the standard wording literally.
p1 was obtained using &, p2 — was not.
Well, on most implementations an expression E1.E2 is equivalent to (&E1)->E2, because the implicit object argument is a pointer, but the standard says that it is a reference and E1->E2 is equivalent to (*(E1)).E2, so I won't take implementation detail as an argument that & is actually implicitly applied.
Also, the standard doesn't specify how `this` pointer is produced, so I don't think that saying "the implicit object argument is a reference, obviously `this` is `&<implicit object argument>`" would be correct.

I've looked at [expr.new]. It also doesn't say that the pointer returned from a non-array new expression is considered as you know what.
This means that in the following code:
```
int main()
{
int* p1 = new int;
int* p2 = &*p1;
}
```
the pointers p1 and p2 have different properties from the operator+'s POV.


Is this intentional?

Brian Bi

unread,
Jul 25, 2018, 10:15:42 AM7/25/18
to std-dis...@isocpp.org
You're right, sorry, I was thinking in terms of older versions of the standard, where the "array of 1 element" paragraph was not a footnote. The wording was changed in C++17 due to CWG 1596. The apparent restriction to pointers obtained through the address-of operator appears to be inadvertent. I think it would be worthwhile to open up another DR to correct the wording.

--

--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi
Reply all
Reply to author
Forward
0 new messages