manav m-n
manav m-n

Reputation: 11394

Pointer to [-1]th index of array

How does a pointer points to [-1]th index of the array produce legal output everytime. What is actually happening in the pointer assignment?

#include<stdio.h>
int main()
{
        int realarray[10];
        int *array = &realarray[-1];

        printf("%p\n", (void *)array);
        return 0;
}

Code output:

manav@workstation:~/knr$ gcc -Wall -pedantic ptr.c
manav@workstation:~/knr$ ./a.out
0xbf841140

EDIT: If this scenario is valid, then can i use this to define an array whose index start from 1 instead of 0, namely: array[1], array[2],...

Upvotes: 14

Views: 20865

Answers (12)

Arun
Arun

Reputation: 20383

The experiment could have provided little more clue if it was the following. Instead of printing the pointer value as

printf("%p\n", (void *)array);

, print the array element value

printf("%d\n", *array);

Thats because printing a pointer with %p will always produce some output (without any misbehavior), but nothing can be deduced from it.

Upvotes: 0

Daniel Newby
Daniel Newby

Reputation: 2432

This is perfectly well defined. Your code is guaranteed to be accepted by all compilers, and never crash at run time. C/C++ pointers are a numeric data type that obey the rules of arithmetic. Addition and subtraction work, and the bracket notation [] is just a fancy syntax for addition. NULL is literally the integer 0.

And this is why C/C++ are dangerous. The compiler will let you create pointers that point anywhere without complaint. Dereferencing the wild pointer in your example, *array = 1234; would produce undefined behavior, anything from subtle corruption to a crash.

Yes, you could use it to index from 1. Don't do this! The C/C++ idiom is to always index from 0. Other people who saw the code indexing from 1 would be tempted to "fix" it to index from 0.

Upvotes: 0

visitor
visitor

Reputation: 8834

In C and C++, array indexes are not checked at runtime. You are performing pointer arithmetic which may or may not end up giving defined results (not here).

However, in C++ you can use an array class that does provide bounds checks, e.g boost::array or std::tr1::array (to be added to standard library in C++0x):

#include <cstdio>
#include <boost/array.hpp>

int main()
{
    try {
        boost::array<int, 10> realarray;
        int* p =  &realarray.at(-1);
        printf("%p\n", (void *)p);
    } catch (const std::exception& e) {
        puts(e.what());
    }
}

Output:

array<>: index out of range

Also produces a compiler warning:

8 test.cpp [Warning] passing negative value -0x000000001' for converting 1 ofT& boost::array::at(size_t) [with T = int, unsigned int N = 10u]'

Upvotes: 2

user266117
user266117

Reputation: 56

You're just pointing to the 4 bytes located before the array.

Upvotes: 0

Šimon T&#243;th
Šimon T&#243;th

Reputation: 36433

a[b] is defined as *(a+b)

therefore a[-1] is *(a-1)

Whether a-1 is a valid pointer and therefore the dereference is valid depends on the context the code is used in.

Upvotes: 10

unwind
unwind

Reputation: 399753

Youre simply getting a pointer that contains the address of that "imaginary" location, i.e. the location of the first element &realarray[0] minus the size of one element.

This is undefined behavior, and might break horribly if, for instance, your machine has a segmented memory architecture. It's working because the compiler writer has chosen to implement the arithmetic as outlined above; that could change at any moment, and another compiler might behave totally differently.

Upvotes: 15

caf
caf

Reputation: 239011

Although, as others have noted, it is undefined behaviour in this case, it compiles without warnings because in general, foo[-1] might be valid.

For example, this is fine:

int realarray[10] = { 10, 20, 30, 40 };
int *array = &realarray[2];

printf("%d\n", array[-1]);

Upvotes: 3

Pavunkumar
Pavunkumar

Reputation: 5335

Here you just performing the pointer arithmetic , It will get firs index address of the relarray

See, if you &relarray[+1] , you would get the second element address of the array. since

&relarray[0] is pointing the first index address.

Upvotes: 1

Alok Singhal
Alok Singhal

Reputation: 96111

The behavior is undefined. You can only calculate a pointer to any of the elements of an array, or one past, but that's it. You can only dereference a pointer to any of the elements of an array (not the one past pointer). Looking at your variable names, looks like you're asking a question from this C FAQ. I think that the answer on the FAQ is very good.

Upvotes: 3

manav m-n
manav m-n

Reputation: 11394

array points to one location before the starting address of realarray. However, what confused me is why does this compiled without any warnings.

Upvotes: 0

Daniel Daranas
Daniel Daranas

Reputation: 22624

The behaviour is undefined.

What you have observed may have happened in your particular compiler and configuration, but anything may happen in a different situation. You cannot rely on this behaviour at all.

Upvotes: 3

Decado
Decado

Reputation: 356

It simply points to the address of the item just ahead of the array in memory.

The array can simply be thought of as being a pointer. This is then simply decremented by one.

Upvotes: 1

Related Questions