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?
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)