Reputation: 11394
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
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
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
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 of
T& boost::array::at(size_t) [with T = int, unsigned int N = 10u]'
Upvotes: 2
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
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
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
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
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
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
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
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