Akash
Akash

Reputation: 5012

C pointer to pointer

Does

int **p 

and

int *p[1]

mean the same thing? as both can be passed to functions allowing the change the pointer object, also both can be accessed via p[0], *p ?

Update, thanks for your help, tough Memory management seems different. does the access mechanism remain the same

*eg: p[0] becomes *(p+0) & *p (both pointing to something)

Thanks

Upvotes: 2

Views: 549

Answers (6)

Useless
Useless

Reputation: 67822

Not quite.

int **p;

declares a pointer p, which will be used to point at objects of type int *, ie, pointers to int. It doesn't allocate any storage, or point p at anything in particular yet.

int *p[1];

declares an array p of one pointer to int: p's type can decay to int ** when it's passed around, but unlike the first statement, p here has an initial value and some storage is set aside.


Re. the edited question on access syntax: yes, *p == p[0] == *(p+0) for all pointers and arrays.


Re. the comment asking about sizeof: it deals properly with arrays where it can see the declaration, so it gives the total storage size.

void foo()
{
    int **ptr;
    int *array[10];

    sizeof(ptr);   // just the size of the pointer
    sizeof(array); // 10 * sizeof(int *)

    // popular idiom for getting count of elements in array:
    sizeof(array)/sizeof(array[0]);
}

// this would always discard the array size,
// because the argument always decays to a pointer
size_t my_sizeof(int *p) { return sizeof(p); }

Upvotes: 7

John Bode
John Bode

Reputation: 123578

They are not the same thing, although in many cases they can appear to behave the same way.

To make the discussion below flow better, I'm going to take the liberty of renaming your variables:

int **pp;   // pointer to pointer
int *ap[1]; // array of pointer

If an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" whose value is the address of the first element in the array (the exceptions to this rule are when the array expression is an operand of either the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration).

So, suppose you write something like

foo(ap);

The expression ap has type "1-element array of pointer to int", but by the rule above it will be converted to an expression of type "pointer to pointer to int"; thus, the function foo will receive an argument of type int **, not int *[1].

On the other side of the equation, subscripting is defined in terms of pointer arithmetic: E1[E2] is defined as *(E1 + E2) where one of the expressions is a pointer value and the other is an integral value. Thus you can use a subscript operator on pp as though it were an array. This is why we can treat dynamically-allocated buffers as though they were regular arrays:

pp = malloc(sizeof *pp * N); // allocate N pointers to int (type of *pp == int *)
if (pp)
{
  size_t i;
  for (i = 0; i < N; i++)
    pp[i] = ...;             // set pp[i] to point to some int value
}

Now for some major differences. First of all, array expressions may not be the target of an assignment; for example, you can't write something like

ap = some_new_pointer_value();

As mentioned above, array expressions will not be converted to pointer types if they are the operands of either the sizeof or unary & operators. Thus, sizeof ap tells you the number of bytes required to store a 1-element array of type int *, not a pointer to a pointer to int. Similarly, the expression &ap has type int *(*)[1] (pointer to 1-element array of pointer to int), rather than int *** (which would be the case for &pp).

Upvotes: 2

NPE
NPE

Reputation: 500893

To simplify things, you could factor out one level of pointers since it's not relevant to the question.

The question then becomes: what's the difference between T* t and T t[1], where T is some type.

There are several differences, but the most obvious one has to do with memory management: the latter allocates memory for a single value of type T, whereas the the former does not (but it does allocate memory for the pointer).

Upvotes: 4

Graham Borland
Graham Borland

Reputation: 60711

They are different.

int **p

means a pointer to a pointer to an int.

int *p[1]

means an array containing one element, with that element being a pointer to an int.

The second form can be treated the same as the first in some situations, e.g. by passing it to a function.

Upvotes: 1

Alok Save
Alok Save

Reputation: 206636

They are not same:

int **p    

Is a pointer which points to another pointer whose type is int *

while,

int *p[1]; 

Is an array of size 1 to the type int *

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272762

No, they are not the same.

  • int **p is a pointer to a pointer to int.
  • int *p[1] is an array (of length 1) of pointers to int.

Upvotes: 1

Related Questions