int main() {
int b=1, c=3, e=4;
int *a=&b;
a[1]=c;
a[2]=e;
printf("%d, %d, %d\n", a[0], a[1], a[2]);
return 0;
}
The above code yields 1, 3, 4
. Why don't I get a compiler error? The variables don't have to be aligned contiguously in memory, so why can a pointer that stores solely the address of b
also point to the others?
CodePudding user response:
It's called undefined behavior
With undefined behavior anything may happen. It may print 1, 3, 4
but it could also print 42, 42, 42
or the program could crash or your computer could turn off or.... anything
The only valid access is a[0]
but the others are just invalid (aka undefined behavior).
A pointer in C points to one element that you can access using either *pointer
or pointer[0]
.
The C language also allows you to access *(pointer 1)
or pointer[1]
. In that case the compiler expect that you have an array of element. And.. if you don't it's your problem - the compiler kind of trust that you know what you are doing and just generates the equivalent code.
So if you do it wrong (like in your posted code) the compiler won't notice. You just end up with a program that has undefined behavior.
The reason that your code is wrong is that a[1]
will access the memory just after a[0]
(which is b
) and expect that another int
is located there. And that expectation doesn't hold for your program. Maybe it's true and maybe c
is actually located in the memory just after b
but there is no guarantee for that. The compiler may place the variables in memory in any order so we can't tell what the memory after b
(aka a[0]
) contains. So reading it by doing a[1]
is just undefined behavior... we won't know what will happen.
To make things even more "strange"... perhaps c and e isn't present in memory.... in fact that's highly likely for your code...
CodePudding user response:
Pointers and arrays in C - difference
A pointer in C is an address in memory. An array is a contiguous list of values of some type. An array will have enough memory reserved for it to contain all those values; a pointer by itself doesn't have any memory allocated to it beyond that needed to store the address it refers to. As a C programmer, it's your responsibility to make sure that pointers you use refer to valid blocks of memory, and that you don't read from or write to memory locations outside those blocks.
Why don't I get a compiler error?
Because C lets you use array syntax with pointers, and doing so is often valid. Consider:
int b[3]={1, 3, 4};
int *a=&b;
Now b
is an array of int
, and a
points to the beginning of that array, so it's entirely legitimate to read and write a[1]
and a[2]
. But b
only holds 3 integers, so reading a[3]
or a[10]
would be an error.