1

Code

short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);

Output

**p = 10

In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).

What does *p mean in my case? Sorry for very simple question.

I saw C standard and stack overflow, but I couldn't find out something.

op ol
  • 705
  • 4
  • 11
  • 3
    It is `p` that is defined. It is not `*p` or `**p`. – Gerhardh Jan 29 '20 at 07:18
  • 6
    If you don't know the purpose of `*p` for a pointer variable, you don't need SO nor the standard, but a good beginner-level C book. Reading the C standard in particular probably causes more harm than good for beginners. – Lundin Jan 29 '20 at 07:34

4 Answers4

2

For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).

So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].

So

*p = malloc(sizeof(short));

is equal to

p[0] = malloc(sizeof(short));

And

**p = 10;

is equal to

p[0][0] = 10;

(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])


It's important to note that the asterisk * can mean different things in different contexts.

It can be used when declaring a variable, and then it means "declare as pointer":

int *p;  // Declare p as a pointer to an int value

It can be used to dereference a pointer, to get the value the pointer is pointing to:

*p = 0;  // Equal to p[0] = 0

And it can be used as the multiplication operator:

r = a * b;  // Multiply the values in a and b, store the resulting value in r
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Then `*p` is `p[0]` and `**p` is `p[0][0]`. Does it imply `(*p = 10) == (**p = 10)`? – op ol Jan 29 '20 at 07:29
  • 1
    @opol No, `p` is a pointer to a pointer to a `short` value (type `short **`). `*p` is a pointer to a `short` value (type `short *`), and `**p` is a `short` value (type `short`). – Some programmer dude Jan 29 '20 at 07:31
2
short **p = (short **)malloc(sizeof(short *));

This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to

short **p;
p = (short **)malloc(sizeof(short *));

The second line

*p = malloc(sizeof(short));

Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to

p[0] = malloc(sizeof(short));

The third line

**p = 10;

**p is the value of the value of p. It is of type short. It is equivalent to

p[0][0] = 10

In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.

As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
2

What does *p mean when **p is already declared?

short **p = (short **)malloc(sizeof(short *));

(better written as)

short **p = malloc (sizeof *p);

Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?

*p = malloc(sizeof(short));

(equivalent to)

p[0] = malloc (sizeof *p[0]);

Allocates storage for a single short and assigns the starting address for that block of memory to p[0].

**p = 10;

(equivalent to)

*p[0] = 10;

(or)

p[0][0] = 10;

Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.

printf("**p = %d", **p);

Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)

The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.

*p          /* has type pointer-to short */

or the [..] also acts as a dereference such that:

p[0]        /* also has type pointer-to short */

You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:

**p         /* has type short */

and

*p[0]       /* also has type short */

as would

p[0][0]     /* also has type short */

The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)

Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Is `p[0]` superset of `p[0][0]~p[0][n-1]`? Intuitively `p[0]` looks like something related with `p[0][0]`, but actually `*p(== p[0])`, `**p(== p[0][0])` exist separate space. I feel confused. – op ol Jan 29 '20 at 08:05
  • 2
    `p` is a pointer to a block of memory holding **pointers** (you allocated storage for 1 pointer). Each pointer allocated can hold the address for a block of memory holding `short` values. You allocate storage for 1-`short` and assign it to `*p`. So the `"superset"` analogy is thinking in the right direction, but *superset* isn't quite right. Say you want a matrix with 10-rows. You would allocate storage for `10-pointers` and assign that to `p`. Say you want 10-short per-row. You can allocate storage for 10 blocks of 10-short and assign to pointers `p[0] - p[9]`. So you have pointers and shorts – David C. Rankin Jan 29 '20 at 08:12
  • 2
    `p[0]` itself is just the first pointer. (the only one you allocated) If you allocated storage for 10-pointers, then you would have `pointers `p[0]-[9]` available to hold the address of blocks of memory allocated to store `short` values. (however many you need) You allocate `p[0] = malloc (10 * sizeof **p);` storage for 10-short and assign to your first pointer and can access each `short` as `p[0][0], p[0][1], p[0][2], and so on ...` If you likewise allocated `p[1] = malloc ( 10 * sizeof *p[1]);` you can now access `p[1][0], p[1][1], p[1][2], and so on ...` allocate for `p[2]` and so on – David C. Rankin Jan 29 '20 at 08:20
  • Thanks to your explanation, I understand my first question, plus a little bit deeper. My second(maybe final) query is `*p` of `short **p = malloc (sizeof *p);` in your answer(I accept removing type-cast for malloc). I think `*p` is early used at declaration. When declaring `p`, `*p` is also used at the same line. Is this defined behavior? I've found only basic thing about pointer. There isn't complicated or detailed reference in Google, standard. – op ol Jan 29 '20 at 08:47
  • 1
    A pointer is just a normal variable that stores the address where something else can be found. That's it. You are familiar with *immediate* values such as `int i = 5;`, now a pointer `int *b = &i'` would simply hold the address where 5 is stored in memory as its value -- and we now say `b` points to `i`. As long as you always understand what it is your pointer points to, you should have no trouble determining how many levels of indirection have to be removed to get to what you want. – David C. Rankin Jan 29 '20 at 09:05
1

Let me put it in different way,

consider an example,

int x;
int *y = &x;
int **z = &y;
x = 10;

Which simplifies to this,

enter image description here

Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.

What does *p mean in my case?

In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.

TruthSeeker
  • 1,539
  • 11
  • 24