1

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?

1
  • The old clockwise/spiral rule might help you parsing those declarations. Commented Jun 9, 2022 at 13:20

2 Answers 2

2

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)

Sign up to request clarification or add additional context in comments.

3 Comments

So it seems to me that the square brackets always implicitly dereference the pointer just as they implicitly define a double pointer (as you pointed out). Therefore, anytime I have a pointer that points to an array of ints I never have to dereference the pointer object to get at the array so long as square brackets follow?
@hijit An expression like this p[i] where p is a pointer or an array is evaluated like *( p + i ). In case when p is an array then it is implicitly converted to a pointer to its first element. If you have for example int a[] = { 1, 2, 3 }; int *p = a; then the both expressions *p and *a are equivalent to p[0] and a[0].
great, thanks for the explanation, that clarifies things nicely.
1

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

1 Comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.