Hi I am new to C and am trying to understand the nuance between pointers and arrays. Specifically I don't understand what fundamentally distinguishes the following two objects:
int *obj1[N];
int *obj2;
obj2 = malloc(N*sizeof(int))
Both objects provide me essentially an array of pointers but I would reference them differently to retrieve the values they point to:
val1 = *obj1[i];
val2 = obj2[i];
I consider both of them in end effect 'arrays of pointers' (though I understand the use of the word 'array' for the obj2 is not technically correct), however obj2 seems to implicitly recognize that I want the value without the need to dereference with * while obj1 doesn't. Could someone clarify for me the structural difference between these two objects which leads to the above difference in referencing their values?
CodePudding user response:
This declaration
int *obj1[N];
indeed declares an array of objects of the pointer type int *
.
This declaration
int *obj2;
declares an object of the type int *
and in the next statement
obj2 = malloc(N*sizeof(int));
there is allocated memory for an array of N elements of the type int
.
So in this lines
val1 = *obj1[i];
val2 = obj2[i];
that for clarity are better to rewrite like
int val1 = *obj1[i];
int val2 = obj2[i];
you get objects of the type int
. In the first line the expression obj1[i]
yields an object of the type int *
because obj1
is an array of pointer. So to get the pointed object of the type int
you need to dereference the pointer expression obj1[i]
. In the second line the expression obj2[i]
yields an object of the type int
because there was allocated an array of integers.
If you want to allocate an array of pointers of the type int *
you have to write
int **obj2 = malloc(N*sizeof(int *));
In this case to access elements of the both arrays you can write
int val1 = *obj1[i];
int val2 = *obj2[i];
Pay attention to that in this expression obj1[i]
the array designator obj1
is implicitly converted to a pointer of the type int **
to its first element. So the both expressions obj1[i]
and obj2[i]
are equivalently evaluated. Also the both expressions *obj1[i]
and *obj2[i]
are equivalent to obj1[i][0]
and obj2[i][0]
.
On the other hand, you could also write for example
int **obj3 = obj1; // the array is implicitly converted to pointer
//...
int val3 = *obj3[i];
Bear in mind that according to the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1) (E2))). Because of the conversion rules that apply to the binary operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero)
CodePudding user response:
The first is an array of int*
, pointers to int
, supposedly allocated locally (on the stack). They do not point at any valid data yet.
The second is an array of int
allocated dynamically (on the heap). It does not contain any valid values yet.
Both objects provide me essentially an array of pointers
No, see above.
but I would reference them differently
Yeah you will have to since they are different data types used for different purposes.
I consider both of them in end effect 'arrays of pointers'
Again, this is wrong.
To dynamically allocate an array of pointers similar to int *obj1[N];
, you have to do this:
int** ptrptr = malloc(n * sizeof *ptr);
CodePudding user response:
A pointer to int ( int *pointer) can be used similar to a one dimension array.
An array of pointers ( int *array[N]) can be used similar to a two dimension array.
Brackets de-reference the pointer. pointer[1] or array[2][1]
#include <stdio.h>
#include <stdlib.h>
#define N 5
int main ( void) {
int *array[N] = { NULL};
int *pointer = NULL;
if ( NULL == ( pointer = malloc ( sizeof pointer * N))) {
fprintf ( stderr, "malloc problem\n");
exit ( 1);
}
for ( int each = 0; each < N; each) {
pointer[each] = each;
}
for ( int row = 0; row < N; row) {
if ( NULL == ( array[row] = malloc ( sizeof *array * N))) {
fprintf ( stderr, "malloc array problem\n");
exit ( 1);
}
for ( int col = 0; col < N; col) {
array[row][col] = ( row * N) col;
}
}
printf ( "pointer:\n");
printf ( "element:->0->1->2->3->4\n ");
for ( int each = 0; each < N; each) {
printf ( " -", pointer[each]);
}
printf ( "\n\narray elements [row][col]:");
printf ( "\ncol:------->0->1->2->3->4");
for ( int row = 0; row < N; row) {
printf ( "\nrow:%d --> ", row);
for ( int col = 0; col < N; col) {
printf ( " -", array[row][col]);
}
}
printf ( "\n");
int value = array[3][0];
int number = *array[3];
printf ( "number: %d value: %d\n", number, value);
free ( pointer);
for ( int row = 0; row < N; row) {
free ( array[row]);
}
return 0;
}