This is sample code my teacher showed us about \"How to dynamically allocate an array in C?\". But I don\'t fully understand this. Here is the code:
int k;
i
For every type T there exists a type “pointer to T”.
Variables can be declared as being pointers to values of various types, by means of the *
type declarator. To declare a variable as a pointer, precede its name with an asterisk.
Hence "for every type T" also applies to pointer types there exists multi-indirect pointers like char** or int*** and so on. There exists also "pointer to array" types, but they are less common than "array of pointer" (http://en.wikipedia.org/wiki/C_data_types)
so int**
test declares an array of pointers which points to "int arrays"
in the line test = (int **)malloc(k*sizeof(int*));
puts enough memory aside for k amount of (int*
)'s
so there are k amount of pointers to, each pointing to...
test[i] = (int*)malloc(k * sizeof(int));
(each pointer points to an array with the size of k amounts of ints)
Summary...
int** test;
is made up of k amount of pointers each pointing to k amount of ints.
Yes it is perfectly Ok. test
is pointer to pointer and so test[i]
which is equivalent to writing test + i
will be a pointer. For better understanding please have a look on this c - FAQ.
malloc is used to dynamically allocate memory to the test variable think of the * as an array and ** as an array of arrays but rather than passing by value the pointers are used to reference the memory address of the variable. When malloc is called you are allocating memory to the test variable by getting the size of an integer and multiplying by the number of ints the user supplies, because this is not known before the user enters this.
Remember that arrays decays to pointers, and can be used as pointers. And that pointers can be used as arrays. In fact, indexing an array can be seen as a form or pointer arithmetics. For example
int a[3] = { 1, 2, 3 }; /* Define and initialize an array */
printf("a[1] = %d\n", a[1]); /* Use array indexing */
printf("*(a + 1) = %d\n", *(a + 1)); /* Use pointer arithmetic */
Both outputs above will print the second (index 1
) item in the array.
The same way is true about pointers, they can be used with pointer arithmetic, or used with array indexing.
From the above, you can think of a pointer-to-pointer-to.type as an array-of-arrays-of-type. But that's not the whole truth, as they are stored differently in memory. So you can not pass an array-of-arrays as argument to a function which expects a pointer-to-pointer. You can however, after you initialized it, use a pointer-to-pointer with array indexing like normal pointers.
int** is a pointer to a pointer of int. take a look at "right-left" rule
Yes indeed, int**
is a pointer to a pointer. We can also say it is an array of pointers.
test = (int **) malloc(k * sizeof(int*));
This will allocate an array of k
pointers first. malloc
dynamically allocates memory.
test[i] = (int*) malloc(k * sizeof(int));
This is not necessary as it is enough to
test[i] = (int*) malloc(sizeof(int*));
Here we allocate each of the array places to point to a valid memory. However for base types like int
this kind of allocation makes no sense. It is usefull for larger types (structs).
Each pointer can be accessed like an array and vice versa for example following is equivalent.
int a;
test[i] = &a;
(test + i) = &a;
This could be array test
in memory that is allocated beginning at offset 0x10000000:
+------------+------------+ | OFFSET | POINTER | +------------+------------+ | 0x10000000 | 0x20000000 | test[0] +------------+------------+ | 0x10000004 | 0x30000000 | test[1] +------------+------------+ | ... | ...
Each element (in this example 0x2000000 and 0x30000000) are pointers to another allocated memory.
+------------+------------+ | OFFSET | VALUE | +------------+------------+ | 0x20000000 | 0x00000001 | *(test[0]) = 1 +------------+------------+ | ... +------------+------------+ | 0x30000000 | 0x00000002 | *(test[1]) = 2 +------------+------------+ | ...
Each of the values contains space for sizeof(int) only.
In this example, test[0][0]
would be equivalent to *(test[0])
, however test[0][1]
would not be valid since it would access memory that was not allocted.