0

When I run the following code:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int array[100];
    int (*array_ptr)[100];
    void *buff = malloc(500);
    int *ptr;
    printf("array: %p \narray+1: %p\n", array, array+1);
    printf("array_ptr: %p \narray_ptr+1: %p\n", array_ptr, array_ptr+1);
    printf("buff: %p\n", buff);
    printf("ptr: %p\n", ptr);
}

the result is like this:

array: 0x7fffe6dc6bd0
array+1: 0x7fffe6dc6bd4
array_ptr: (nil)
array_ptr+1: 0x190
buff: 0x1f80260
ptr: 0x7fffe6dd417c

I run it multiple times, array, array+1, buff and ptr all change values randomly, but array_ptr and array_prt+1 never change, although the pointer arithmetic result 0x190 is as expected.

Does it indicate that the array pointed by array_ptr is stored in heap? But the dynamically allocated memory chunk pointed by buff is also supposed to be in heap and its value changes, why is that? Thanks!

mzoz
  • 1,273
  • 1
  • 14
  • 28
  • 6
    Your pointer `array_ptr` is *uninitialized*, it doesn't point anywhere, its value will be *indeterminate*. Same with `ptr`. – Some programmer dude Feb 24 '20 at 07:28
  • And in C you [shouldn't really cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Feb 24 '20 at 07:30
  • Thanks @Someprogrammerdude but why is `array_ptr+1`'s value still available? – mzoz Feb 24 '20 at 07:30
  • Lastly, the only things stores in the heap is the 500 bytes you allocate with `malloc`. But note that the storage for the variable `buff` itself isn't on the heap, it only points to the heap. – Some programmer dude Feb 24 '20 at 07:31
  • It so happens that on your system the value of `array_ptr` is `NULL`. On a PC-like system this is equal to `0`. For a 32-bit (4-byte) `int` then `100 * 4` is `400`, or `0x190`. `0 + sizeof *array_ptr` therefore is `0x190`. – Some programmer dude Feb 24 '20 at 07:34
  • Also remember that for any pointer or array `p` and index `i`, the expression `*(p + i)` is exactly equal to `p[i]`. From which follows that `p + i` is equal to `&p[i]`. That means e.g. `array_ptr + 1` is equal to `&array_ptr[1]`. And since `array_ptr` is uninitialized that really leads to *undefined behavior* (dereferencing invalid pointers is UB). You're "lucky" that the compiler doesn't actually do the dereference but only the addition. – Some programmer dude Feb 24 '20 at 07:45
  • 1
    This can´t get compiled. You need to `#include `in order to use `malloc`. – RobertS supports Monica Cellio Feb 24 '20 at 09:13

2 Answers2

1

array_ptr is uninitialized pointer, and gets an undefined value(in your case 0).

array_ptr+1 is sizeof(int)*100 = 400 = 0x190 more than array_ptr

ptr is also an uninit pointer, which in your case points to garbage.

You need to initialize pointers after they're defined to get any valid results

To your question, array is on the stack, buff is on the heap, and ptr/array_ptr are uninitialized will give you garbage or segmentation fault if you try to access their data

Shlomi Agiv
  • 1,183
  • 7
  • 17
0

Does it indicate that the array pointed by array_ptr is stored in heap?

No. array_ptr points to nothing, neither on the stack nor on the heap.


int (*array_ptr)[100];

array_ptr is one pointer to an array of 100 int objects, but with this statement you do not create an array with 100 int objects by which array_ptr is pointing to the first element of this array. It only creates the pointer itself.

With:

printf("array_ptr: %p \narray_ptr+1: %p\n", array_ptr, array_ptr+1);

You are trying to print the addresses of objects the pointer array_ptr and its offset by 1 point to, but this isn´t possible since array_ptr is not initialized to point to such objects. Thus, You´ll get any kind of Undefined Behavior/ unpredictable results.

You need to initialize array_ptr with, f.e. the address of the first int object of array:

int (*array_ptr)[100] = array;

The same goes for the pointer ptr with:

printf("ptr: %p\n", ptr);

ptr needs to have an address of an object it points to in order to show the address of that object.

But the dynamically allocated memory chunk pointed by buff is also supposed to be in heap and its value changes, why is that?

This is a completely different thing. With malloc you do allocate memory on the heap (if it was successful of course) and you do get a pointer to that memory back, which isn´t the case with int (*array_ptr)[100];.

  • The undefined behavior in this case seems to be that the uninitialized variable `array_ptr` has the value 0 (whether that happens to be the incidental value on the stack where the variable resides or whether it's a debug mode initialization we don't know); and consequently, incrementing it points "to the next array", which would be 400 resp. 0x190 bytes behind it (the memory occupied by an array of 100 ints). 0 + 400 = 400, which is the address printed. – Peter - Reinstate Monica Feb 24 '20 at 23:25