Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Address one past the end of array - is this syntax a valid C++?

134 views
Skip to first unread message

Peter

unread,
Feb 1, 2014, 12:23:39 PM2/1/14
to
Assume we have an array:

int arr[5];

It's legal to refer to address arr + 5, but, of course, illegal to refer to element arr[5] as it's not part of the array. However, arr + n is equivalent to &arr[n]. My question is: does this equivalence also hold for an edge case of
n = 5 (or, generally, n equal to number of elements of array)?

While there's nothing wrong with arr + 5, &arr[5] looks highly suspicious: it looks like in the first step arr[5] is evaluated (which introduces an undefined behaviour) which would mean the expression as a whole is undefined. Does the equivalence still hold in this special case?

Victor Bazarov

unread,
Feb 1, 2014, 5:36:06 PM2/1/14
to
I would not be surprised at the validity of this after I've learned that
initializing a reference by dereferencing a null pointer is now legal.
*nullptr creates a special kind of reference, and the only useful
operation you can do with it is to take its address, which in turn
should give you null, as I understand it. So, using the same logic, the
expression a[n] is the same as *(a+n), which is to give you a reference
to a non-existing element (one beyond the last in the array) and with
that reference the only valid operation is to take its address.
According to the precedence rules, &arr[5] is evaluated as &(*(arr+5)),
which is OK (if you subscribe to the invalid reference idea and the
validity of applying the 'address of' operator to it).

V
--
I do not respond to top-posted replies, please don't ask

Mr Flibble

unread,
Feb 1, 2014, 6:33:02 PM2/1/14
to
Bullshit mate; dereferencing null pointers is UB.

/Flibble

bblaz

unread,
Feb 2, 2014, 7:39:39 AM2/2/14
to
Not always true.

Dereferencing pointers which do not point to valid objects is undefined
behavior if the program necessitates the lvalue-to-rvalue conversion of
the *arr expression.
see 4.1 #1.

5.3.1 #3
The result of the unary & operator is a pointer to its operand. The
operand shall be either an lvalue of type
other than “array of runtime bound” or a qualified-id.

Evaluation of &*arr expression does not necessitate the lvalue-to-rvalue
conversion, hence its legal.


Also 5.3.1 #1
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 ]

blaz



Dombo

unread,
Feb 2, 2014, 9:36:16 AM2/2/14
to
Op 01-Feb-14 23:36, Victor Bazarov schreef:
I'm not sure this is the case; according to the C++ 11 draft standard
(N3337): "Note: std::nullptr_t is a distinct type that is neither a
pointer type nor a pointer to member type; rather, a prvalue of this
type is a null pointer constant and can be converted to a null pointer
value or null member pointer value.". I.e. since nullptr is not a
pointer type the fact that you can legally dereference it (which
surprised me a bit, but I suppose there is a good reason for it),
doesn't necessarily mean that it is also legal to dereference a pointer
referencing a non-existing element.

Mr Flibble

unread,
Feb 2, 2014, 11:47:48 AM2/2/14
to
More bullshit. It is always true mate; dereferencing null pointers is UB.

8.3.2/5

"A reference shall be initialized to refer to a valid object
or function. [ Note: in particular, a null reference cannot exist in a
well-defined program, because the only
way to create such a reference would be to bind it to the “object”
obtained by dereferencing a null pointer,
which causes undefined behavior. As described in 9.6, a reference cannot
be bound directly to a bit-field.
—end note ]"

[snipped unrelated Standard quotes]

/Flibble

bblaz

unread,
Feb 2, 2014, 1:43:53 PM2/2/14
to
& is an unary operator & not a reference type. I think your quote is
irrelevant in this case.

blaz

bblaz

unread,
Feb 2, 2014, 1:45:18 PM2/2/14
to
To be clear, i was refering to the op.

James Kanze

unread,
Feb 14, 2014, 10:30:07 AM2/14/14
to
On Saturday, 1 February 2014 17:23:39 UTC, Peter wrote:
> Assume we have an array:

> int arr[5];

> It's legal to refer to address arr + 5, but, of course,
> illegal to refer to element arr[5] as it's not part of the
> array. However, arr + n is equivalent to &arr[n].

No it's not. They're only equivalent if the expression "arr[n]"
is a valid expression.

> My question
> is: does this equivalence also hold for an edge case of
> n = 5 (or, generally, n equal to number of elements of array)?

> While there's nothing wrong with arr + 5, &arr[5] looks highly
> suspicious: it looks like in the first step arr[5] is
> evaluated (which introduces an undefined behaviour) which
> would mean the expression as a whole is undefined.

Exactly.

> Does the
> equivalence still hold in this special case?

No. "arr + 5" is legal, and corresponds to a pointer one beyond
the end of the array. "&arr[5]" is undefined behavior.

C has a special rule to allow "&arr[5]". Back before C++03 (and
even before C++98, I think), there was some discussion about
allowing this in C++, but in the end, the special case was not
adopted. (I think part of the motivation for not adopting it is
that you couldn't make it work with user defined containers,
like std::vector. Something like:

std::vector<int> v(5);
int* p = &v[5];

will crash, at least in debug mode, in all of the
implementations I use.)

--
James

James Kanze

unread,
Feb 14, 2014, 10:35:47 AM2/14/14
to
On Saturday, 1 February 2014 22:36:06 UTC, Victor Bazarov wrote:
[...]
> I would not be surprised at the validity of this after I've learned that
> initializing a reference by dereferencing a null pointer is now legal.
> *nullptr creates a special kind of reference, and the only useful
> operation you can do with it is to take its address, which in turn
> should give you null, as I understand it.

Just curious, but where did you get this information from?
I can't find it in the standard (looking in the obvious places,
which isn't always enough).

--
James

Victor Bazarov

unread,
Feb 14, 2014, 11:12:50 AM2/14/14
to
I can't give you the exact source, unfortunately, and I am sorry. All I
can remember is that it was mentioned here, discussed in some thread,
and at the time my claim of undefined behavior of initializing a
reference by dereferencing a null pointer was contradicted, and upon
investigating I found that the lvalue to rvalue conversion that used to
be necessary and was the cause of the UB in such a case was not any
longer a requirement (or it was that I incorrectly remembered that
conversion was needed). And in a blink of an eye, so to speak, UB was
not there anymore.

I'm likely too gullible when C++ is concerned. Next you're going to
tell me that atoi is not a standard function, and I'll believe it. :-)

Mr Flibble

unread,
Feb 14, 2014, 11:42:27 AM2/14/14
to
On 14/02/2014 16:12, Victor Bazarov wrote:
> On 2/14/2014 10:35 AM, James Kanze wrote:
>> On Saturday, 1 February 2014 22:36:06 UTC, Victor Bazarov wrote:
>> [...]
>>> I would not be surprised at the validity of this after I've learned that
>>> initializing a reference by dereferencing a null pointer is now legal.
>>> *nullptr creates a special kind of reference, and the only useful
>>> operation you can do with it is to take its address, which in turn
>>> should give you null, as I understand it.
>>
>> Just curious, but where did you get this information from?
>> I can't find it in the standard (looking in the obvious places,
>> which isn't always enough).
>
> I can't give you the exact source, unfortunately, and I am sorry. All I
> can remember is that it was mentioned here, discussed in some thread,
> and at the time my claim of undefined behavior of initializing a
> reference by dereferencing a null pointer was contradicted, and upon
> investigating I found that the lvalue to rvalue conversion that used to
> be necessary and was the cause of the UB in such a case was not any
> longer a requirement (or it was that I incorrectly remembered that
> conversion was needed). And in a blink of an eye, so to speak, UB was
> not there anymore.

Bullshit mate: dereferencing null pointers is UB, period.

/Flibble

woodb...@gmail.com

unread,
Feb 17, 2014, 6:30:05 PM2/17/14
to
On Friday, February 14, 2014 10:12:50 AM UTC-6, Victor Bazarov wrote:
>
> I can't give you the exact source, unfortunately, and I am sorry. All I
> can remember is that it was mentioned here, discussed in some thread,

This might be it:

https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B/null$20reference$20victor|sort:date/comp.lang.c++/NtyXDAepnxw/-eL5DDzoO-8J
0 new messages