1
#include<stdio.h>
#include<stdlib.h>

int main()
{
     int i, j;
     int(*p)[3];
     p = (int(*)[3])malloc(3*sizeof(*p));
     for(i=0; i<3; i++)
     {
         for(j=0; j<3; j++)
             printf("%d", p[i][j]);
     }
     return 0;
}

p is a pointer to an array of 3 integer then why it is behaving as a 2D array

rishabh
  • 35
  • 1
  • 5

2 Answers2

2

It is a completely superfluous cast that only adds clutter. Or in case of C++ it is needed, but you should never be using malloc in C++...

p is an array pointer to an array of type int [3]. *p is an array and therefore 3*sizeof(*p) gives the size of 3 such arrays, 3*3*sizeof(int). So the code allocates an array of arrays - a 2D array.

p is set to point at the first element of that array. p[i] is pointer arithmetic on an array pointer and gives you array number i. Therefore a pointer to a 1D array can be used to access a 2D array.

A better way to write the malloc call would be this:

p = malloc( sizeof(int[3][3]) );

You example never initializes the arrays, so printing their contents would give garbage and possibly undefined behavior. Corrected code:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
     int(*p)[3];
     p = malloc( sizeof(int[3][3]) );
     for(size_t i=0; i<3; i++)
     {
         for(size_t j=0; j<3; j++)
         {
             p[i][j] = (int)j;
             printf("%d ", p[i][j]);
         }
         printf("\n");
     }

     free(p);
     return 0;
}

Related topic: Correctly allocating multi-dimensional arrays.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Not. It is not a completely superfluous cast. Indeed **it is dangerous** (as documented widely). In case you have forgotten to `#include ` and you have different sizes for pointers and integers (as happens in 64 bit architectures) the compiler will asume `malloc()` returns an integer and will get an integer from it, that will be cast to a pointer (introducing false data for the truncated result of the proper `malloc()` routine) **without warning** making undefined behaviour to arise. In case you don't cast, a warning about malloc being called without a prototype willl be issued. – Luis Colorado Apr 04 '17 at 15:18
  • @LuisColorado I am perfectly aware of that old bug that indeed existed in the 1990s. I can see why you would be concerned if assume that people still use the ancient C90 standard which is 28 years old. Good news! It is the year 2017 and we use a version of the C standard where function declarations are mandatory and we have been doing so for the past 18 years. Forgetting stdlib.h is therefore completely harmless, since the code will not even compile. You may beat the dead horse [here](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/22538350#22538350). – Lundin Apr 04 '17 at 15:49
  • I expect you have never to deal with a pre-ansi compiler, congratulations for living so actualized. Normally, having to use an old compiler is not a matter of taste or preference, but some requirement in some project sometimes. And then you had better to know... believe me or not... I don't worry about that. It seems you have been disapointed by my comment, but it was not addressed to you, nor to be offensive, but to illustrate some ancient problem that happens to occur nowadays. – Luis Colorado Apr 04 '17 at 17:06
  • @LuisColorado Most of my career I have worked with C90. When starting new projects though, I pick a tool chain which is up to date with the C standard. Refusing to use old crap is how you force tool vendors to improve. – Lundin Apr 05 '17 at 06:39
  • As for your comment, if you check the tag wiki of the C tag, it states that when the tag is used, the current standard is always assumed unless the question explicitly says otherwise. The whole "don't cast the result of malloc" debate, which has gone way out of proportion on SO, is an old, well-known issue that doesn't apply on standard compilers, simple as that. – Lundin Apr 05 '17 at 06:48
-1

malloc is a command to allocate a block of memory according to the size of data you needed (in byte). in this case you are trying to allocate a block of memory for an array of integer with size of 3. meanwhile sizeof() is a method to get actual byte size of memory would be used for a data type which is an integer in this case. and because you are needing an array with size of 3, that's why the 3 multiplier comes for and than you would like to type cast as an pointer into an array of integer with size of 3 to be used later

Ferico Samuel
  • 195
  • 3
  • 15
  • 3
    "in this case you are trying to allocate a block of memory for an array of integer with size of 3" No, the code allocates 3 such arrays. "memory would be used for a data type which is an integer in this case" No, `sizeof(*p)` gives the size of an array of 3 integers. I'm afraid this answer is overall incorrect. – Lundin Apr 03 '17 at 08:54