My teacher told me that int **array is not a 2D array, it is just a pointer to a pointer to an integer.
Now, in one of my projects I have to dynamically allocate a 2D array of structs, and this is how it is done:
struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
for (int i = 0; i < columns; i++) {
array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}
But here we return a pointer to a pointer to the struct, so how is this a 2D array?
Before using dynamic allocation, I had a statically allocated array of the form:
array2d[][]
Now that I replaced it by dynamic allocation, I also replaced array2d[][] by **array2d.
Every function that takes array2d[i][j] als argument now returns an error saying the types don't match.
Could someone explain me what is happening here? What is the difference between **array and array[m][n] and why is the compiler complaining?
They're thoroughly different things.
An array is a sequence of values of the same type stored one after another in memory.
In C, an array is more or less interchangeable with a pointer to its first element — a[0] is *a,
a[1] is *(a+1), etc. — at least when we're talking about one-dimensional arrays.
But now consider:
int a[3][3];
in this case, a contains nine elements, contiguous in memory. a[0][0] through a[0][2], then a[1][0] immediately after, up until a[2][2].
If you pass a to a function, it would fit into a parameter type of int * or int[3][3] or int [][3] (knowing the "stride" of the second dimension is absolutely necessary to doing the math to look up a given element).
On the other hand:
int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);
in this case, b is an array of 3 elements, each of which is a pointer to an array of 3 elements. You still access it like b[0]0] or b[1][2], but something completely different is happening under the hood. The elements aren't all stored contiguously in memory, and *b isn't any of them, it's a pointer. If we were to pass b to a function, we would receive it with a parameter of type int ** or int *[]. Knowing the length of each row in advance isn't necessary, and in fact each row could have a different length from the others. Some of the rows could even be null pointers, with no storage behind them for integers.
Related
I'm very new to C and I have trouble understanding array pointers. I'm trying to make a array bigger,I copy all of its element to new bigger array but I can't make original variable to point the new array. I'm use to C# where you can do
double[] array1 = new double[5];
double[] array2 = new double[10];
array1 = array2;
I did something similar using int array
int array1 [5];
int array2 [10];
*array1 = &array2;
and it compile but crash the program. Same lines but double or char[] (I was told to use char[] instead of sting in C) do not even compile
[Error] incompatible types when assigning to type 'double' from type 'double (*)[(sizetype)(newsize)]'
The results I found on the topic told me to use double* array1 for variable type but this change the interactions with that variable.
If someone can explain the concept to me or at least tell me what to search for that will be huge help.
I do know the basics of pointers!
There are a few things you need to know about arrays (and pointers):
The first is that arrays and pointers are two different things;
The second is that an array can decay to a pointer to its first element. So if you use array1 (from your example) when a pointer is expected, that's the same as doing &array1[0]. The type of such a pointer is a pointer to a single element type (so for array1 the type will be int *);
The third thing is that for any array of pointer a and index i, the expression a[i] is exactly equal to *(a + i). That means *array1 (again from your example) is the same as array1[0] (*array1 is equal to *(array1 + 0) which is equal to array1[0]);
An array will have a fixed size. Once defined the size of an array can't change;
Lastly when you get a pointer to an array (as in &array2) then you get a pointer to the actual array, not to one of its elements. The type of e.g. &array2 is int (*)[10].
Now we can puzzle together the statement
*array1 = &array2;
If we do the array-indexing replacement for *array1 then we get
array[0] = &array2;
And here we can see a big problem: The type of a single element of array1 is a plain int. So what the assignment is trying to do is to assign a pointer to an array (of type int (*)[10]) to a single int.
If you want to copy all the elements from one array to another, then use the memcpy function. You're not allowed to assign between arrays.
But beware of the different sizes for array1 and array2. If you go out of bounds of an array (or other allocated memory) you will have undefined behavior.
In C there is no way to make an array variable "reference" a different variable. If you need to use "references" they can be emulated using pointers:
int *pointer1 = array1; // array1 here will decay to &array[0]
int *pointer2 = array2; // Same here for array2
With the above definition pointer1 is (in a way) "referencing" array1. You can now use pointer1 and array1 almost interchangeably.
One major difference between using pointers and arrays is how their sizes are calculated: When you do sizeof on an array you get the size (in bytes) of the whole array. Assuming 32-bit int (the most common) then sizeof array1 will return 5 * 4 (or 20) as the size. If you get the size of a pointer, you get the size of the pointer itself, not what it might point to. So sizeof pointer1 will return either 4 or 8 (depending on if you're in a 32-bit or 64-bit system).
Going back to references, we can now change where pointer1 is pointing:
pointer1 = pointer2; // Assuming pointer2 is unchanged, equivalent to pointer1 = array2
Now pointer1 and pointer2 are pointing to the same array, array2.
In C# you can overload the = to copy the arrays. In C it is just simple assignment.
In C arrays decays to pointers for the sake of simplicity. In C *(array + N) == array[N] and *array == array[0]
int array1 [5]; it is not the array of pointers only integers so *array1 = &array2; assigns array[0] with address of the first element of the the array2 converted to signed integer which generally doesn't make too much sense and it does not copy array2 to array
To copy array you need to use memcpy or the loop to copy the element. You need to make sure that the destination array is large enough to accommodate the second array. C will not change the destination array size.
The assignments that your are doing is wrong. Basically a pointer points to a block of memory. from your code I can understand that array1 = array2; and *array1 = &array2; is wrong.
Syntax in C is something like this data-type* pointer-variable = (data-type*)malloc(no. of bytes you want);
See consider you want 10 block of memory of type int
int *p = (int *)malloc(10 * sizeof(int))
sizeof(int) return 4 bytes.
Now p points to 10 * 4 = 40 bytes of memory, I multiplied by 4 because int is usually of 4 bytes and double is of 8 bytes and so on.
Follow this link to understand C - Data Types
Now regarding changing pointers refer below example and read the comments
int *q = NULL // declare a pointer of same type as the block of memory it is going to point
q = p; //now q and p point same memory of 40 bytes, means value at q[0] is equal to p[0]
When you have an integer pointer and you increment it by p++ it will point to next memory location p[1], pointer will be exactly incremented by 4 bytes as int size is 4 bytes and for double it will be 8 bytes, for char it will be 1 byte and so on.
Now if you want to increase the size of dynamically allocated memory you can use realloc please follow this link to understand more.
Dynamic Memory Allocation in C
int *p = NULL;
// Dynamically allocate memory using malloc()
p = (int*)malloc(no. of bytes, sizeof(int));
// Dynamically re-allocate memory using realloc()
p = realloc(p, (no. of bytes) * sizeof(int));
// Avoid memory leaks
free(p);
Syntax in C++ is something like this data-type* pointer-variable = new data-type[size];
See consider you want 10 block of memory of type int
int *p = new int[10]
Just use new operator to allocate block of memory and use delete to free allocated memory to avoid memory leaks.follow this link
new and delete operators in C++ for dynamic memory
Or If you are looking for containers where you don't know how much memory should be allocated the use standard template library vector, it helps creating dynamic arrays.follow this link
Vector in C++ STL
I wrote the code -
int arr2d[2][2] = {{1, 2}, {3, 4}};
int * arr = (int*)arr2d;
int i = 0;
for(i = 0; i < 4; i++)
{
printf("%d ", arr[i]);
}
The output was as if I printed every element in the arrays in arr2d, nothing out of the ordinary.
Why is that so?
Why can I cast from int** (as a 2 dimension array) to int*?
You have a misunderstanding. Arrays are not pointers. They do decay to pointers in most contexts, but that's a question of evaluation, not nature. Accordingly, 2D arrays are arrays of arrays, not arrays of pointers. Thus, they do not decay to pointers to pointers, but rather pointers to arrays. There is no int** involved anywhere in your code.
Given this declaration:
int arr2d[2][2] = {{1, 2}, {3, 4}};
The relevant pointer assignment you can perform without a cast is
int (*arr2d_ptr)[2];
arr2d_ptr = arr2d; // arr2d is not a pointer, but it does decay to one in this expression
arr2d_ptr is a pointer to a two-element array of int. The assignment makes it point to the first element of arr2d. If you convert that to type int *, then the result points to the first int in the array to which arr2d_ptr points. For example,
int *ip = (int *) arr2d_ptr;
That's natural, because that int is exactly the first part of the array. You can access it by index as ip[0] or *ip. And you can access the second int in that array as ip[1].
I guess the other facet of the question is about the expressions ip[2] and ip[3]. Arrays are contiguous sequences of elements. Arrays of arrays are not special in this regard: they are contiguous sequences of (smaller) arrays. Thus, the layout of your arr2d is like this:
array..|array..|
. If you overlay the layout of each of the member arrays then you get this:
int|int|int|int|
, which is exactly the same as the layout of a one-dimensional array of four int. This is why you can access all four ints by indexing ip (or arr in your example code).
Fun fact: because expressions of array type decay to pointers, you don't need a cast here. You could instead dereference arr2d_ptr to form an expression designating the first element of the 2D array, which is a 1D array, and let that decay to a pointer:
int *ip2 = *arr2d_ptr;
or, equivalently,
int *ip3 = *arr2d;
The values are stored in memory as if it was a linear array. That's why you can access them like that.
It doesn't work when the 2 dimensional array is composed out of pointers, and I have to understand why.
If you are working with an array of pointers you'll have to use a pointer to pointer, aka, double pointer.
It seems logic that if you want a pointer to access elements in an array of pointers you'll need a pointer to pointer.
//...
int *arr2d[2][2];
int **arr = (int**)arr2d;
//...
If you want to use it as a 2D array, which is what you would want in most cases, you can use:
Live sample
#include <stdio.h>
#include <string.h>
int main()
{
int arr2d[2][2] = {{1, 2}, {3, 4}};
int(*arr)[2] = arr2d; //pointer to 2d array with 2 columns
for (int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
printf("%d ", arr[i][j]); //use it as if it were a 2d array
}
putchar('\n');
}
}
A double pointer is not to be confused with a 2D array, these are different things, this thread has a nice explanation of what each of these mean.
In memory, the array char a[4] = {1, 2, 3, 4} looks likes this:
[(1)(2)(3)(4)]
with () representing a byte of memory and [] hinting you where the array begins/ends.
The array char a[2][2] = {{1, 2}, {3, 4}} looks like this in memory:
[[(1)(2)][(3)(4)]]
See, there is no difference, as [] don't really exist in memory, they are just hints I used in my reply. Effectively, if you don't know anything about the arrays and just look at the content of the raw bytes in memory, you'll see:
(1)(2)(3)(4)
in both cases.
Thus instead of creating an array a[Xmax][Ymax] and accessing the elements using a[x][y], you can as well create the array as b[Xmax * Ymax] and access the elements using b[x * Xmax + y], as that's in fact what happens behind the scenes anyway.
And in C, you can always turn an array reference into a pointer, as an array reference is a reference to a memory location where an array is located and a pointer is a reference to a memory location (regardless if an array is located there or not). So
int a[5] = { ... };
int * b = a;
works as a is a reference to an int array, which are just several int values stored in memory, and b is a pointer to a memory location where an int value is stored. Well, at the address where the array a starts, an int value is stored, so this assignment is perfectly correct.
And m[3] just means "increase the memory address m references three times by the size of the value type m references and fetch the value from that address". And that works and returns the expected value, no matter if m is a pointer or an array reference. So while this syntax is actually intended for array access, it also works with pointers.
The syntax for a pointer would actually be *(m + 3), which means "increase the pointer address three times by the size of the value type it points to and then fetch the value from that address". Yet, just in the first case, this syntax would work with an array reference as well, since an array reference can always become a pointer when required.
These two are different programs for declaring a 2D array
1)i think they are same because both are 2D array?
2)can we access both using a[i][j] and p[i][j]?
3)Why *a or a are same and p or *p are different
#include<stdio.h>
#include<stdlib.h>
int main(){
int a[100][100];
printf("%d\n",a);
printf("%d\n",*a);
int **p=malloc(sizeof(int*)*100);
for(int i=0;i<100;i++){
p[i]=malloc(sizeof(int)*100);
}
printf("%d",p);
printf("%d",*p);
}
the big difference is that in case with a[100][100] the compiler knows the full size of the array and allocates a contiguous memory region on a stack (as in your case) or in static area. When accessing an array element, the compiler is free to calculate its address based on the array dimensions and use a single reference to access it. like this
[0,0][0,1][0,2]...[0,99][1,0][1,1][1,2]...[99,0]...[99,99]
+-------0------...-----+----- 1 -------...+----- 99 -----+
In case of the dynamic allocation, which you used, the memory is allocated contiguously only for a single dimension of the array. So, you allocate 100 pointers, every one of each points to a single dimensional array of integers. Those arrays can be placed at arbitrary memory locations. As a result, the compiler has to do at least 2 references in this case, use first index to get a pointer to the second array, than use the second index to get the element in the second array.
pointers[index0] : [0][1][2]..[99]
/ | \
/ | |
V V V
[0] [0] [0]
[1] [1] [1]
... ... ...
some addition about a and *a. In 'c' when the name of the array is used in a pointer like context, it is interpreted as an address of the array. So, in printf a points to the beginning of the two-dimensional array. *a for same reason is supposed to provide you an address of the first column. Which in this case is the same as the start or the array. **a will point you to the very first array element a[0][0]. And by the way, it is better to use %p there instead of %d for pointers.
You can see that for the dynamic array p gives you the address of the array of pointers, whether *p gives you the value of its first element p[0] which by itself is a pointer to the column. The addresses are definitely different.
But in both cases you can use a[i][j] and p[i][j] to access array elements.
They are not the same. The first (int a[100][100]) is a single variable that is a compound object. The other (int **p) is a collection of arrays that you are using as a data structure for matrices.
If you want to have an actual 2D array in dynamic storage, this is how you do it:
#include <stdlib.h>
int main()
{
int (*m)[100][100];
m = malloc(sizeof *m);
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
(*m)[i][j] = 0;
}
Of course, the syntax is a bit weird, and you would rather have a dynamic matrix with variadic number of columns and rows, which is why you would prefer to declare a matrix pointed by int **p.
The reason why a and *a give the same output is because both decay to a pointer to the first element of a, which is a[0][0]. On the other hand, p is a pointer itself, and *p is the contents of the variable pointed by p. They are just as different as they would be if you did this:
int d = 0;
int *p = &d;
printf("%p\n", p);
printf("%d\n", *p);
Now back to your int **p.
Yes, you can access both int a[][100] and int **p with double indexing. However, there is a fundamental difference in the way the compiler treats a[i][j] and p[i][j].
In a[i][j], each a[i] is an array of 100 integer objects. So in order to access the i-th element, and then the j-th element, the compiler has to acess the i*100+j-th element from a[0][0]. This access can be performed in a single step with some index arithmetic.
In v[i][j], each v[i] is a pointer which may point to objects far from each other in memory. In order to acess the element v[i][j], the compiler must first follow p to the array *p, then find the i-th element in this array, which is a pointer to the array p[i]. And then with some pointer arithmetic it will find the j-th element of this array.
a is the address of the array in memory, its value depends on how your compiler and operating system layout memory. *a is the value in memory at that location, again depending on your operating system this is either random or set to some pre-determined value. Similarly for p and *p
For ease of debugging most operating systems set memory to some deliberate fixed value. Unix typically sets malloc() memory to zero.
Windows has a range of default contents depending on how the memory was allocated see: When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?
Three questions in 1.
If I have a 2-D array -
int array_name[num_rows][num_columns]
So it consists of num_rows arrays -each of which is an array of size = num_columns. Its equivalent representation using an array of pointers is-
int* array_name[num_rows]
-so the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right? I saw some texts telling
int* array_name[num_columns]
will the indices not get switched in this case ?
For a ID array I specify size dynamically as-
int *p;
p = (int*) malloc (size * sizeof(int))
For 2 D arrays do I specify the size of entire 2-D array or of one 1-D array in malloc -
int*p [row_count];
p = (int*) malloc (row_count * column_count * sizeof(int))
or
p = (int*) malloc (column_count * sizeof(int))
I think it should be the second since p is a pointer to a 1-D array and p+1 is a pointer to a 1-D array etc. Please clarify.
For ques 2 - what if p was defined as -
int **p; rather than
int * p[row_count]
How will the malloc be used then? I think it should be -
p = (int*) malloc (row_count * column_count * sizeof(int))
Please correct, confirm, improve.
Declaring :
int *array_name[num_rows];
or :
int *array_name[num_columns];
is the same thing. Only the name changes, but your variable is still referring to rows because C is a row major so you should name it row.
Here is how to allocate a 2D array :
int (*p)[column] = malloc (sizeof(int[row][column]);
An int ** can be allocated whereas int [][] is a temporary array defined only in the scope of your function.
Don't forget that a semicolon is needed at the end of nearly every line.
You should read this page for a more complete explanation of the subject
(and 2.)
If I have a 2-D array
int array_name[num_rows][num_columns];
So it consists of num_rows arrays -each of which is an array of size = num_columns.
If both num_rows and num_columns are known at compile time, that line declares an array of num_rows arrays of num_columns ints, which, yes, is commonly referred as a 2D array of int.
Since C99 (and optionally in C11) you can use two variables unknown at compile time and end up declaring a Variable-Length Array, instead.
Its equivalent representation using an array of pointers is
int* array_name[num_rows];
So the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right?
Technically, now array_name is declared as an array of num_rows pointers to int, not arrays. To "complete" the "2D array", one should traverse the array and allocate memory for each row. Note that the rows could have different sizes.
Using this form:
int (*array_name)[num_columns];
// ^ ^ note the parenthesis
array_name = malloc(num_rows * sizeof *array_name);
Here, array_name is declared as a pointer to an array of num_columns ints and then the desired number of rows is allocated.
3.
what if p was defined as int **p;
The other answers show how to allocate memory in this case, but while it is widely used, it isn't always the best solution. See e.g.:
Correctly allocating multi-dimensional arrays
I know that, for the following:
int a[10];
a is a pointer of the type int * to a[0], while &a is a pointer of type int (*)[10].
Now my question is for the following 2D array:
int b[20][30];
Is b a pointer of the type int **? Or is it a pointer of the type int (*)[30]?
Is &b a pointer of the type int (*)[20][30]?
Arrays are not pointers (this point cannot be stressed enough).
That being said, an array decays to a pointer to its first element. For example:
int a[10];
int b[20][30];
void print_a(int *);
void print_b(int (*)[30]);
print_a(a);
print_b(b);
The first element of a is a[0], and similarly the first element of b is b[0]. You basically take that first dimension away, and change it to a (*); I'll explain more in a moment since it is a bit more complex than that.
The relationship between pointers and arrays is riddled with contextual subtleties that aren't terribly difficult to grasp, but the size information in various scopes makes it interesting and also helps to give you an idea of how the decay works:
#include <stdio.h>
int h(int *pa)
{
printf("h(int *): sizeof pa=%zu\n", sizeof pa);
printf("h(int *): sizeof *pa=%zu\n", sizeof *pa);
return *pa;
}
int g(int (*pa)[5])
{
printf("g(int (*)[5]): sizeof pa=%zu\n", sizeof pa);
printf("g(int (*)[5]): sizeof *pa=%zu\n", sizeof *pa);
return h(*pa);
}
int f(int (*pa)[3][5])
{
printf("f(int (*)[3][5]): sizeof pa=%zu\n", sizeof pa);
printf("f(int (*)[3][5]): sizeof *pa=%zu\n", sizeof *pa);
return g(*pa);
}
int main(void)
{
int arr[2][3][5] = {{{11235}}};
printf("main: sizeof arr=%zu\n", sizeof arr);
printf("main: sizeof *arr=%zu\n", sizeof *arr);
printf("%d\n", f(arr));
}
Every pointer is the same size (this may not always be true on all platforms!), but by dereferencing the pointer, you see the size of a given element of the array, whether you dereference using the unary * operator or the [N] array notation, which is equivalent to *((array)+(N)) by definition.
Anyway, going back to the difference between pointers and arrays, you should understand that int[20][30] is not the same as int **. Why is that? Because of the fact that int[20][30] decays to a pointer of type int(*)[30], no more decay can occur until the pointer is dereferenced. Moreover, int ** is actually int *(*), which means it can point to the first element of an array of pointers. That is, int ** might have once been int *[N].
int foo[x][y][z] <=> int (*foo)[y][z]
int *foo[m][n] <=> int *(*foo)[n]
int (*foo[a])[b] <=> int (**foo)[b]
In the first case, we have a 3-D array, which decays to a pointer to a 2-D array; in other words, an array of arrays and a pointer to an array are closely related and interchangeable in many contexts aside from the size issue. The first dimension x is the one that decays, leaving the y and z dimensions.
In the second case, we have a 2-D array of pointers. This decays to a pointer to an array of pointers. Again, an array of arrays is closely related to a pointer to an array, and dimension m decays, leaving dimension n.
In the third case, we have an array of pointers to arrays. It decays to a pointer to a pointer to an array. Since dimension a is closest to the variable name, that is the one that decays, leaving dimension b. Note that since it is an array of pointers to arrays, the pointers could point to the first element of arrays themselves:
int arr[2][3][5];
int (*foo[2])[5] = { arr[0], arr[1] };
int (**foo_ptr)[5] = foo;
Recap:
Array (size A) of arrays (size B) <=> Pointer to array (size B)
Array (size A) of pointers <=> Pointer to pointer
The array that decays/grows is always the innermost array/pointer, the innermost being the one closest to the variable name in the variable declaration, with arrays having higher associativity than pointers, though of course parentheses make all the difference.
This rabbit hole obviously can be confusing, but I hope I helped a bit at least!
First of all make it clear that arrays are not pointers. Relationship between pointers and arrays is subtle. I would suggest you to read second chapter of tutorial on pointers by Ted Jensen first.
I would like to tell you something in a nutshell what has been describe in this chap. Consider following example.
int a[10];
int *p;
Now you can write
p=a;
that is equivalent to
p=&a[0];
This thing make many texts to say array is name of pointer. But it is better if you say "the name of the array is the address of first element in the array" .
Because though you can write
p=a;
but you can not write
a=p;
Now come to your question:
From above discussion it should be clear that b is not pointer of type int** .For example:
int b[10][10];
int **x;
int *p;
b=&p; // this is error
x=&p; // this fine
For your other questions you may use online CDECL.
if you write
int b[10][10]; --> declare b as array 10 of array 10 of int
int (*p)[10]; --> declare p as pointer to array 10 of int
int (*p)[10][20]; --> declare p as pointer to array 10 of array 20 of int
No, a is not of type int*, it is of type int [10] (i. e. of an array type). This is why sizeof(a) will give you the size of the array (40 bytes, assuming 32 bit integers).
Likewise, b is of type int [20][30], which is nothing other than an array of arrays. I. e. sizeof(b[0]) is the size of one line array, which is 120 in this case, the size of the entire array (sizeof(b)) is 20 times the size of the line arrays, which is 2400 bytes in this case.
The trick is, that an array decays into a pointer to its first element in almost all contexts. So when you do pointer arithmetic (as in b[3]) on the 2D array, b decays into a pointer of type int (*)[30], so the pointer arithmetic skips rows, adding three times the size of a row (360 bytes in this case) - the rows are the elements of the 2D array. The resulting type of b[3] is int [30], i. e. the dereferenced pointer.
Once you have dereferenced to a row array with b[3], you can again invoke pointer arithmetic to select the correct element in this row (b[3][5]). Again, the array-pointer-decay is invoked, the mechanic is the same.
Note that there is no pointer array involved as is the case when you emulate a 2D array with an int**. The double dereference b[3][5] translates into something like ((int*)b)[3*30 + 5] by virtue of array-pointer-decay, only the element itself is accessed from memory.
int* temp;
int arraySize = 20;
temp = (int *)malloc(arraySize * sizeof(int));
This will create a section in memory 20 "ints" long, similarly as you mentioned.
int** temp;
int arraySize = 20;
int rowSize = 10;
temp = (int **)malloc(arraySize * sizeof(int *));
for(i=0; i<arraySize; i++){
temp[i] = (int *)malloc(rowSize * sizeof(int));
}
That is what the 2D array would actually look like.
temp[0] would give you the address of the first "array". In which you could do something like above int *array = temp[0] then access it like a normal array but using *array[0] to get the value.
2D arrays really don't mesh well with pointers and saying *temp[0] to get the values of the first array. You can try to mess with it, you'll figure it out, but don't have a machine that can compile C with me right now.
Reference that may help: http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html