2

i am trying to create a 2d array using double pointer... my code is...


int **p1;
p1=(int **) malloc(2*sizeof(int *));
for(int i=0;i<2;i++)
{
    p1[i]=(int *) malloc(3*sizeof(int));
    for(int j=0;j<3;j++)
    {
       scanf("%d",(p1+i)+j);
    }

}
for(int i=0;i<2;i++)
{

    for(int j=0;j<3;j++)
    {
       printf("%d\n",*(*(p1+i)+j));
    }

}

as i have declared a double pointer (**p1) for it and i am able to put data at all those places using my scan scanf("%d",(p1+i)+j); statement. And to dereference i can use print statement as i have done printf("%d\n",*(*(p1+i)+j));

but why it is breaking during print statement but accepting my scan statement.

but why this is giving me correct response...

int mybox[][4]={{1,2,3,4},{5,6,7,8}};//we have to provide subscript;
for(int i=0;i<2;i++){
     for(int j=0;j<4;j++){
        printf("%d",mybox[i][j]);//will print all elements
        }
}
        printf("%d",*(*(mybox)+1));//give me 2
        printf("%d",*(*(mybox+1)+1));//give me 6
        printf("%d",*(*(mybox+1)+3));//give me 8
3
  • "why is it breaking" -- What is the error message? Commented Aug 24, 2011 at 16:49
  • An unhandled exception of type 'System.NullReferenceException' occurred in myapp.exe Additional information: Object reference not set to an instance of an object. Commented Aug 24, 2011 at 16:51
  • @cnicutar actually i m working on visual studio 2010 express Commented Aug 24, 2011 at 17:14

4 Answers 4

4

Your scanf portion is implemented incorrectly. It destroys your data. Ironically, the problem does not reveal itself during scanf phase, but instead causes a crash at printf stage.

The correct scanf code might look as follows

for(int i=0;i<2;i++)
{
    p1[i]=(int *) malloc(3*sizeof(int));
    for(int j=0;j<3;j++)
    {
       scanf("%d",*(p1+i)+j);
    }
}

Note the extra *. What you really need here is

scanf("%d", &(*(*(p1 + i)) + j));

You can write it this way if you want. But you can notice that the outer & "annihilates" with the next nested *, so the above is equivalent to

scanf("%d", *(p1 + i) + j);

However, my advice to you is to stop using the barely-readable *-and-+ combination for array element access and start using the [] instead. This is how your code should have looked from the very beginning

...
scanf("%d", &p1[i][j]);
...
printf("%d\n", p1[i][j]);

On top of that, since this is taggged C, avoid using sizeof with types as much as possible and stop casting the result of malloc. A better variant would be

int **p1;

p1 = malloc(2 * sizeof *p1);
for(int i = 0; i<2; i++)
{
  p1[i] = malloc(3 * sizeof *p1[i]);
  ...   
Sign up to request clarification or add additional context in comments.

7 Comments

p1 is a pointer to pointer then how can i dereference it using only 1 *
becuase int this you are looking for a pointer, not for a value pointed by a pointer
can you suggest me good article to learn double pointer and 2d arrays
@teacher: I added the explanation for "only one *" to the answer.
@teacher: The problem with typecasting is that it is completely unnecessary and can be dangerous (see here c-faq.com/malloc/mallocnocast.html). When you use sizeof operator, it is better to use it with expressions instead of type names. That way your code becomes more type-independent. It becomes easier to maintain. (Imagine you need to change int to double. How many places you'd need to fix in your version and in mine?).
|
2
scanf("%d",(p1+i)+j);

This is wrong, and not what you expect. Associativity says that a+b+c == (a+b) + c == a + (b+c).

Avoid direct pointer arithmetic because it is hell confusing when you are new to the language. Prefer:

   scanf("%d", &p1[i][j]);

   printf("%d\n", p1[i][j]);

The generated assembly code is exactly the same as if you went for direct pointer arithmetic.

Also, unrelated but important, do not cast the return type of malloc(), as this may hide potential bugs in your code (like the lack of a #include <stdlib.h>, which is very important).


Keep in mind that the types int** and int[][N] are quite different in their implementation. Assumptions made for one are not true for the other, even though you can access the elements using the same var[i][j] syntax.

Your second example gives the correct answer because it is... correct? That is it. The second example doesn't have any scanf(), which is where your problem is in the first example.

2 Comments

thank you sir but can you explain how to achieve same results using pointer not "p1[i][j]"
You could have passed *(p1+i)+j to sscanf() (note the leading *, because you want to derreference the result of the p1+i pointer to get the other pointer before adding j to it). But don't do that, since it makes your code less readable. Again, just say exactly what you want to say. You want to pass the address of p1[i][j] to sscanf(), then just say it with a & in front.
0

This creates a 2d array where all data is stored in adjacent memory cells on the heap (as opposed to the ** syntax more commonly seen). It uses the concept of array pointers which you can read about in the C lang FAQ.

int (*ptr)[X]; 
ptr = malloc(X * Y * sizeof(int));

And yes, you can use the ptr[x][y] if you malloc in this way.

3 Comments

Yes, but this is only possible when X is a compile-time constant. If so, the recommended and much more elegant way to allocate memory would be ptr = malloc(Y * sizeof *ptr);.
I agree, although that will not make the [][] syntax possible, which the OP asked for.
Er... I don't see what you mean. An array allocated as shown above will be perfectly accessible as ptr[i][j]. The only difference in my comment is how the size is calculated.
0
scanf("%d\n",(*(p1+i)+j));

replace your scanf for taking the array values...

Comments

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.