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],...
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.
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.
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.
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.
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]);
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]'
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.
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.
array
points to one location before the starting address of realarray
. However, what confused me is why does this compiled without any warnings.
You're just pointing to the 4 bytes located before the array.
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.
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.
精彩评论