boxed__l
boxed__l

Reputation: 1336

Why does C support negative array indices?

From this post in SO, it is clear that C supports negative indices.

  1. Why support such a potential memory violation in a program?

  2. Shouldn't the compiler throw a Negative Index warning at least? (am using GCC)

  3. Or is this calculation done in runtime?

EDIT 1: Can anybody hint at its uses?

EDIT 2: for 3.) Using counters of loops in [] of arrays/pointers indicates Run-time Calculation of Indices.

Upvotes: 15

Views: 12719

Answers (8)

NZD
NZD

Reputation: 1970

Example of using negative array indices.

I use negative indices to check message protocols. For example, one protocol format looks like:

<nnn/message/f>

or, equally valid:

<nnn/message>

The parameter f is optional and must be a single character if supplied.

If I want to get to the value of character f, I first get a pointer to the > character:

char * end_ptr = strchr(msg, '>');
char f_char = '1';  /* default value */    

Now I check if f is supplied and extract it (here is where the negative array index is used):

if (end_ptr[-2] == '/')
{
    f_char = end_ptr[-1];
}

Note that I've left out error checking and other code that is not relevant to this example.

Upvotes: 0

Taymon
Taymon

Reputation: 25676

Array subscripts are just syntactic sugar for dereferencing of pointers to arbitrary places in memory. The compiler can't warn you about negative indexes because it doesn't know at compile time where a pointer will be pointing to. Any given pointer arithmetic expression might or might not result in a valid address for memory access.

Upvotes: 4

chux
chux

Reputation: 153498

OP: Why support ... a potential memory violation?

It has potential uses, for as OP says it is a potential violation and not certain memory violation. C is about allowing users to do many things, include all the rope they need to hang themselves.

OP: ... throw a Negative Index warning ...

If concerned, use unsigned index or better yet, use size_t.

OP ... calculation done in runtime?

Yes, quite often as in a[i], where i is not a constant.

OP: hint at its uses?

Example: one is processing a point in an array of points (Pt) and want to determine if the mid-point is a candidate for removal as it is co-incident. Assume the calling function has already determined that the Mid is neither the first nor last point.

static int IsCoincident(Pt *Mid) {
  Pt *Left = &Mid[-1];   // fixed negative index
  Pt *Right = &Mid[+1]; 
  return foo(Left, Mid, Right);
} 

Upvotes: 4

dragonroot
dragonroot

Reputation: 5821

a[b] does the same thing as *(a+b). Since the latter allows the negative b, so does the former.

Upvotes: 0

Eric Postpischil
Eric Postpischil

Reputation: 222734

Here is an example of use.

An Infinite Impulse Response filter is calculated partially from recent previous output values. Typically, there will be some array of input values and an array where output values are to be placed. If the current output element is yi, then yi may be calculated as yi = a0•xi + a1•xi–1 +a2•yi–1 +a3•yi–2.

A natural way to write code for this is something like:

void IIR(float *x, float *y, size_t n)
{
    for (i = 0; i < n; ++i)
        y[i] = a0*x[i] + a1*x[i-1] + a2*y[i-1] + a3*y[i-2];
}

Observe that when i is zero, y[i-1] and y[i-2] have negative indices. In this case, the caller is responsible for creating an array, setting the initial two elements to “starter values” for the output (often either zero or values held over from a previous buffer), and passing a pointer to where the first new value is to be written. Thus, this routine, IRR, normally receives a pointer into the middle of an array and uses negative indices to address some elements.

Upvotes: 11

Ziffusion
Ziffusion

Reputation: 8923

The calculation is done at runtime.

Negative indices don't necessarily have to cause a violation, and have their uses.

For example, let's say you have a pointer that is currently pointing to the 10th element in an array. Now, if you need to access the 8th element without changing the pointer, you can do that easily by using a negative index of -2.

char data[] = "01234567890123456789";
char* ptr = &data[9];
char c = ptr[-2]; // 7

Upvotes: 22

Yu Hao
Yu Hao

Reputation: 122383

Why support such a potential memory violation in a program?

Because it follows the pointer arithmetic, and may be useful in certain case.

Shouldn't the compiler throw a Negative Index warning at least? (am using GCC)

The same reason the compiler won't warn you when you access array[10] when the array has only 10 elements. Because it leaves that work to the programmers.

Or is this calculation done in runtime?

Yes, the calculation is done in runtime.

Upvotes: 9

user1666959
user1666959

Reputation: 1855

Elaborating on Taymon's answer:

float arr[10];
float *p = &arr[2];

p[-2]

is now perfectly OK. I haven't seen a good use of negative indices, but why should the standard exclude it if it is in general undecidable whether you are pointing outside of a valid range.

Upvotes: 5

Related Questions