3

I am coding a 3D array using triple pointers with malloc. I replaced *ptrdate in (a), *ptrdate[i], and *ptrdate[i] with *ptrdate in the code below since They are all basically pointers of type Date but access in different dimension. I got the same results both ways.

Question: what's the difference when used as the operand of sizeof?

typedef struct {
    int day;
} Date;

int main(){
  int i, j, k, count=0;
  int row=3, col=4, dep=5;

  Date ***ptrdate = malloc(row * sizeof *ptrdate); //(a)
  for (i=0; i<row; i++) {
    ptrdate[i] = malloc(col * sizeof *ptrdate[i]); //(b)
    for (j=0; j<col; j++) {
      ptrdate[i][j] = malloc(dep * sizeof *ptrdate[i][j]); //(c)
    }
  }
LED Fantom
  • 1,229
  • 1
  • 12
  • 32
  • You mean what's the difference when used as the operand of `sizeof`? – Kerrek SB Apr 25 '15 at 07:37
  • Why did you replace them if you don't know what they mean? To answer your question, think of the types of the expressions `ptrdate`, `*ptrdate`, and `*ptrdate[i]`. – juanchopanza Apr 25 '15 at 07:40
  • @juanchopanza , The last `malloc` would be wrong when using `sizeof *ptrdate` , right? The same goes for the second `malloc` too, right? – Spikatrix Apr 25 '15 at 07:42
  • @PumpkinCake , Try printing `sizeof *ptrdate`, `sizeof *ptrdate[i]` and `sizeof *ptrdate[i][j]` using the `%zu` format specifier in the `printf` – Spikatrix Apr 25 '15 at 08:05
  • 4
    **The question marked as duplicate is certainly not a duplicate. Please vote to reopen.** – autistic Apr 25 '15 at 08:28
  • 1
    "They are all basically pointers of type Date". That's a bold and incorrect statement. – n. m. could be an AI Dec 07 '15 at 15:19

2 Answers2

2

I am coding a 3D array using triple pointers with malloc.

First of all, there is no need for any array to be allocated using more than one call to malloc. In fact, it is incorrect to do so, as the word "array" is considered to denote a single block of contiguous memory, i.e. one allocation. I'll get to that later, but first, your question:

Question: what's the difference when used as the operand of sizeof?

The answer, though obvious, is often misunderstood. They're different pointer types, which coincidentally have the same size and representation on your system... but they might have different sizes and representations on other systems. It is important to keep that possibility in mind, so that you can be sure your code is as portable as possible.

Given size_t row=3, col=4, dep=5;, you can declare an array like so: Date array[row][col][dep];. I know you have no use for such a declaration in this question... Bear with me for a moment. If we printf("%zu\n", sizeof array);, it'll print row * col * dep * sizeof (Date). It knows the full size of the array, including all of the dimensions... and this is exactly how many bytes are required when allocating such an array.

printf("%zu\n", sizeof ptrDate); with ptrDate declared as in your code will produce something entirely different, though... It'll produce the size of a pointer (to pointer to pointer to Date, not to be confused with pointer to Date or pointer to pointer to Date) on your system. All of the size information, regarding the number of dimensions (e.g. the row * col * dep multiplication) is lost, because we haven't told our pointers to maintain that size information. We can still find sizeof (Date) by using sizeof *ptrDate, though, because we've told our code to keep that size information associated with the pointer type.

What if we could tell our pointers to maintain the other size information (the dimensions), though? What if we could write ptrDate = malloc(row * sizeof *ptrDate);, and have sizeof *ptrDate equal to col * dep * sizeof (Date)? This would simplify allocation, wouldn't it?

This brings us back to my introduction: There is a way to perform all of this allocation using one single malloc. It's a simple pattern to remember, but a difficult pattern to understand (and probably appropriate to ask another question about):

Date (*ptrDate)[col][dep] = malloc(row * sizeof *ptrDate);

Suffice to say, usage is still mostly the same. You can still use this like ptrDate[x][y][z]... There is one thing that doesn't seem quite right, though, and that is sizeof ptrDate still yields the size of a pointer (to array[col][dep] of Date) and sizeof *ptrDate doesn't contain the row dimension (hence the multiplication in the malloc above. I'll leave it as an exercise to you to work out whether a solution is necessary for that...

free(ptrDate); // Ooops! I must remember to free the memory I have allocated!
autistic
  • 1
  • 3
  • 35
  • 80
0

int *ptr is the declaration of pointer which stores the address of the integer variable and int **ptr is the declaration that stores the address of the pointer storing the integer variable.

asapxj07
  • 351
  • 3
  • 8