Rectangle 27 0

c++ Is negative index for operator[] well defined?


*(p + N)
N[p]
p[N]

@black: So does the former. And I mentioned that at the top of my post.

An interesting upshot of this is that this:

Not sure if I'd call it "up"-shot. ;-p Is N[p] ever useful?

The latter example assumes the use of the built-in subscript operator.

Yes, it is well defined. Built-in operator[] is defined in terms of pointer arithmetic. This:

where p is a pointer and N is an integer, is equivalent to this:

Note
Rectangle 27 0

c++ Is negative index for operator[] well defined?


#include <iostream>

class Point
{
public:    
    Point( int x, int y ) : x( x ), y( y ) {}
    int x, y;
};

class Circle
{
public:    
    Circle( unsigned int r ) : r( r ) {}

    Circle & operator []( Point p )
    {
        std::cout << "Drawing a circle at ( " << p.x << ", " << p.y << " )\n";
        return *this;
    }

    unsigned int r;
};        

int main()
{
    Circle circle( 10 );

    circle[ { 0, 0 } ];
}
Drawing a circle at ( 0, 0 )

1 A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type array of T or pointer to T and the other shall have unscoped enumeration or integral type. The result is of type T. The type T shall be a completely-defined object type.65 The expression E1[E2] is identical (by definition) to *((E1)+(E2)) ...

So you may use any integral type including type int and correspondingly negative values provided that the result of expression *((E1)+(E2)) is well-formed.

Take into account that for user-defined types you may use a brace-init-list as the index. For example

Note
Rectangle 27 0

c++ Is negative index for operator[] well defined?


@immibis I decided to leave that out, as this question is about the validity of the negative index; the indirection is separate, although it's obviously related to the result, which is defined in the second quote. If adding information about the indirection would help the OP I'd be happy to add it, but I don't think it's necessary.

Since q points to an element of an array object of a valid size for your integral expression, it is semantically valid.

So your expression is the same as *(q-1) = 41;, so is syntactically valid.

The expression E1[E2] is identical (by definition) to *((E1)+(E2)).

What about the *?

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression.

Note
Rectangle 27 0

c++ Is negative index for operator[] well defined?


int* p = new int[3];
int* q = p + 2;
*(q-1) = 41;

It is perfectly safe and portable. You are just using pointer arithmetic to address the memory allocated by the new operator.

Note
Rectangle 27 0

c++ Is negative index for operator[] well defined?


x[idx] = (*(x +idx)) = (*(idx + x)) = idx[x]

Notice that we can rewrite it in many ways (just like algebra).

The index operator x[idx] equals (*(x +idx)) and yes idx might be negative. However, you have to ensure that the dereferenced pointer was pointing to a valid memory address.

Note
Rectangle 27 0

c++ Is negative index for operator[] well defined?


delete[] p;

Also, you can set the pointer q to any element of the array, and in addition, to one element past the array. (Don't attempt to dereference an element on past the end of the seat though.)

It's absolutely fine so long as you don't attempt to dereference a pointer outside the bounds of the array pointed to by p.

Note