0

I tryed to create a multi-dimensional array and I wrote a function but when I check my matrices, I've realized my pointers's values are the same but their addresses are diffrent. Why :)

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

int **matrix(int a,int b){
    int i;
    int **x;
    x = (int**)malloc(a * sizeof(int*));
    for (i = 0; i < a; i++) {
        x[i] = (int*)malloc(b * sizeof(int));
    }
    return x;
}

int main()
{
    int **m1, **m2;
    m1=matrix(3,3);
    m2=matrix(3,3);
    printf("Values: %d %d\n",m1[1][1],m2[1][1]);
    printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);
    return 0;
}
Berk Sahin
  • 11
  • 4
  • [Don't cast malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Dec 20 '13 at 12:47
  • 3
    Your values are uninitialized, so they can be anything. The addresses should be different, why did you expect the same? – Leeor Dec 20 '13 at 12:48
  • after the allocation of m1 it gets an address. Then when m2 is allocated, it is allocated in a different address as m1 still exist and has not been de-allocated yet(dynamically allocated). – Kaustav Ray Dec 20 '13 at 12:54
  • cause of I got the same results. I use code block and my screen output is Values: 3870600 3870600 Addresses: 3870684 3770780 – Berk Sahin Dec 20 '13 at 12:56
  • sorry for my english .s – Berk Sahin Dec 20 '13 at 13:00
  • As already said, the first two values can be anything and the second two values are addresses which ought to be different ! – Kaustav Ray Dec 20 '13 at 13:01
  • so there is no reason to be same values, they can be anything – Berk Sahin Dec 20 '13 at 13:07

2 Answers2

1

In case of m1[1][1], you are printing values in the array. They are not pointer values. Since you have not initialized them to any value, they can be anything. In your case, they are turning up to be same
&m1[1][1] is a pointer though. Since you are allocating memory twice, they have different values. (Different addresses for array)

Tanmay Patil
  • 6,882
  • 2
  • 25
  • 45
0

Memory-leak-looming!
First off, you have a possible memory-leaking program here. You are allocating memory for 2 matrices, but at no point to you free the allocated memory. You should. All memory allocated on the heap is your responsibility, it is your job to see to it that that memory is free'ed once you're done with it. Possibly implement a function like:

void free_matrix(int **matrix, int len)
{
    if (matrix == NULL) return;//don't try and free NULL pointers
    while(len--) free(matrix[len]);
    free(matrix);
}

to be called in your main function after you've printed out what needed printing out:

free_matrix(m1, 3);
m1 = NULL;//setting unused pointers to NULL is a good habit
free_matrix(m1,3);//won't cause problems
free_matrix(m2, 3);
free_matrix(m2, 1);//ERROR!

You also fail to check if and see if the malloc call actually was successful. If there isn't enough memory available, malloc returns null, and you should handle this. At the very least do:

some_ptr = malloc(sizeof(*some_ptr));
if (some_ptr == NULL) exit(EXIT_FAILURE);//macro expands to 1

Anyway, I've written this codepad that tries to free and reassign the same matrix over and over, until the values in memory are different. As it turns out, on codepad at least, they're alwasy the same.
I'm currently browsing linux kernel code, and the web, to see if there is a reason for this. Perhaps Linux wipes the heap memory when the kernel is idling, or perhaps it's a codepad thing... either way, stay tuned for updates :)

Basically, malloc doesn't initialize the memory it allocates. What the OS does with free'd memory is up to the OS. I've tried the code below on my 64bit linux system, which compiled fine using

gcc -std=c99 -Wall src.c -o temp

And it shows that the matrices do contain different values, but were, in my case mostly 0. Anyway, here's the code:

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

void **matrix(int a,int b)
{
    int i;
    unsigned int **x;
    x = malloc(a * sizeof(*x));
    if (x == NULL) exit(EXIT_FAILURE);
    for (i = 0; i < a; i++)
    {
        x[i] = malloc(b * sizeof(*(x[i])));
        if (x[i] == NULL) exit(EXIT_FAILURE);
    }
    return (void **)x;
}

void free_matrix(void ***m, int l)
{
    if (*m == NULL) return;
    while(l--) free((*m)[l]);
    free(*m);
*m = NULL;
}

int main( void )
{
    unsigned int **m1, **m2, c=0;
    m1 = (unsigned int **) matrix(3,3);
    m2 = (unsigned int **) matrix(3,3);
    printf("%lu <> %lu\n", sizeof(m1[1][1]), sizeof(m1));//4 <> 4 -> 32 bit, 4 <> 8 -> 64
    while(*(m1[1]+1) == *(m2[1]+1) && c < 101)
    {
        ++c;
        free_matrix((void ***) &m1,3);
        m1 = (unsigned int **) matrix(3,3);
    }
    if (c == 101)
    {
        for(c=0;c<3;++c) printf("%u %u %u\n%u %u %u\n\n",*(m1[c]), *(m1[c]+1), *(m1[c]+2),*(m2[c]), *(m2[c]+1), *(m2[c]+2));
    }
    else
    {
        printf("Different vals after %d tries\n", c);
    }
    printf("Values: %u %u %c\n",m1[1][1],m2[1][1], (unsigned char) m1[1][1]);
    printf("Addresses: %p %p\n",(void *) (m1[1]+1), (void *) (m2[1]+1));
    free_matrix((void ***)&m1, 3);
    free_matrix((void ***)&m2,3);
    return 0;
}

And an example of the output I got is here:

4  8
12546112 0 0
0 0 0

12546144 0 0
0 0 0

0 0 0
0 0 0

Values: 0 0
Addresses: 0xbf7054 0xbf70d4

Anyway, I hope this, and the rest of my answer clears a thing or two up for you.

To get the actual addresses you'll have to write:

printf("Addresses: %p, %p\n", (void *) &m1[1][1], (void *)&m1);

As opposed to:

printf("Addresses: %d %d",&m1[1][1],&m2[1][1]);

Because m1[1][1] isn't a pointer! m1 is a pointer to a pointer to an int, so m[1] is a pointer to an int, and m1[1][1] is an int, not a pointer.

Oh, and casting the return value of malloc is not done. It hides possible errors, and malloc will return a compatible pointer type or NULL anyway.

But why are their addresses not the same? well simple: you're allocating 2 separate blocks of heap memory. You're not allocating the same memory twice (that would be impossible).
You're attempting to print out the address of those values that are stored in 2 separate locations in the heap.

It's like building 2 houses that are exactly the same in every way, only you build them in a different city. Their addresses will be unique.

The fact that the values are the same is a coincidence. malloc does not change the contents of the memory, so if the blocks of memory happened to be set to 0 since last they were used, then you'll happen to get zero initialized memory, but you can't be sure this will always be the case... The question you should be asking is not why, but why not or what are the odds

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • actually I want to asked why are values the same but i guess asked wrong question cause of I already know the addresses must be different – Berk Sahin Dec 20 '13 at 13:34
  • @BerkSahin: coincidence, Added that to my answer – Elias Van Ootegem Dec 20 '13 at 13:46
  • @BerkSahin: I've done some more digging, and looked at your code. Check the codepad I linked to in my answer, which fixes a couple of issues with your code, and read the rest of my edit, because there might be a future update comming – Elias Van Ootegem Dec 20 '13 at 14:43