Member Avatar for I_m_rude

hi,

int a[][2]={1,2,3,4};
 int *p[]={(int*)a,(int*)a+1, (int*)a+2};

 for(i=0;i<2;i++)
 for(j=0;j<2;j++)
 printf("%d ",*(*(p+i)+j));

Firstly, This is part of any code. And i want to ask that in p[] definition, why it is written (int) with every element since a is already an pointer.
Secondly, when I am accessing ((p+1)+1) element in loop, then why it is giving o/p "3"(without quotes) ? Becuase according to me, (p+1) means "(int)a+1" which in turn means first element of the 2nd row. am i right ?
because a+1 means we are incrementing the row in 2-D array. please make me correct if i am wrong.

thanks in advance. please help.

First of all a isn't a pointer, it's an array. It decays to a pointer in certain contexts, but it decays to a pointer to an int-array, not a pointer to an int, so you need to cast it if you want to use it as an int-pointer.

And yes, a+1 would give you a pointer to the second row of a. However you're not doing a+1, you're doing (int*)a + 1. So you cast a to a pointer to an int, not an array. So incrementing it by 1 will cause it to point to the next int, not to the next row. Basically a is used as if it was a flat array instead of an array of arrays on line 2. So the pointers in p point to 1, 2 and 3 respectively.

And i want to ask that in p[] definition, why it is written (int) with every element since a is already an pointer.

It's already a pointer, but the type is different. Try removing the cast and you'll get an error similar to: "type mismatch between int(*)[2] and int*"

The fact that the cast hides an error should give you pause when writing code like this, because it suggests that you're doing something stupid. In particular, it's not safe to assume that you can pun a 2D array into a 1D array using a pointer because there's potential padding at the end of each 1D array in a 2D array that could produce trap representations.

Member Avatar for I_m_rude

@deceptikon will you please write it in again into more simpler form ? please!!

Member Avatar for I_m_rude

@sepp2k will you please tell me what "decays" means ? I have read it at more than 20 places. but I never get it's meaning. if any body asks me a[] is an array or pointer or both ? then what should i say to him/her ? please elaborate!
thanks.

a[] is an array.
arrays decays into pointers.
for example if we are having a[i], it decays into *(a+i) as far as i know

@deceptikon will you please write it in again into more simpler form ?

It really depends on what you want the code to do, but if you're trying to display the contents of the 2D array with pointer notation, you don't even need an intermediate pointer variable:

#include <stdio.h>

int main(void)
{
    /* This is better because it highlights the structure of the array more clearly */
    int a[][2] =
    {
        {1, 2},
        {3, 4}
    };
    int i, j;

    /* At the very least, use braces around the outer loops */
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 2; j++)
        {
            /* Note how the pointer notation still works with an array variable. */
            printf("%d ", *(*(a + i) + j));
        }
    }

    /* This makes output cleaner for the next program */
    putchar('\n');

    return 0;
}

@sepp2k will you please tell me what "decays" means ? I have read it at more than 20 places. but I never get it's meaning. if any body asks me a[] is an array or pointer or both ? then what should i say to him/her ? please elaborate!

"Decays" is used because pointers are seen as lower level entities from arrays. What really happens is an array variable name, when used in value context, will be converted to a pointer to the first element of the array. Thus the following two printf() calls are functionally identical:

int a[] = {1, 2, 3};

printf("%d\n", *a);
printf("%d\n", *(&a[0]));

If you read my description carefully, you might be asking what "value context" is. Value context is when you're requesting the value stored by a variable's referenced object. The other context would be object context where you're trying to find some attribute of the object referenced by a variable. Just about everything constitutes value context, with three exceptions in the case of an array:

  1. As an operand to the sizeof operator. In sizeof a, a is being used in object context and as a result, the expression will produce the size of the whole array in bytes. If it were used in value context, the expression would evaluate to the size of a pointer due to the array name to pointer conversion explained previously.

  2. As an operation to the address-of (&) operator. When you say &a, you get a pointer to an array, not a pointer to a pointer to the first element. If this expression were evaluated in value context, it would be impossible to create a pointer to an array, which would be problematic as that's the type of nested dimensions in a multidimensional array.

  3. As a string literal initializer. This is an edge case, but in char a[] = "test", "test" is being used in object context rather than value context. This case is really nothing more than trivia, because it doesn't change how you use or think about the expression.

So the whole "is an array an array or a pointer?" question can be answered simply, if cryptically: an array object is always an array, but when used in value context, an array variable is converted into a pointer to its 0th element.

Member Avatar for I_m_rude

hey, @deceptikon
this explaination is awesome!
one last point i wana ask which is generated from this explanitaion only.
will you please this line again ? "As an operation to the address-of (&) operator. When you say &a, you get a pointer to an array, not a pointer to a pointer to the first element. If this expression were evaluated in value context, it would be impossible to create a pointer to an array, which would be problematic as that's the type of nested dimensions in a multidimensional array."

"

one last point i wana ask which is generated from this explanitaion only.
will you please this line again ? "As an operation to the address-of (&) operator. When you say &a, you get a pointer to an array, not a pointer to a pointer to the first element. If this expression were evaluated in value context, it would be impossible to create a pointer to an array, which would be problematic as that's the type of nested dimensions in a multidimensional array."

I suspect you haven't yet encountered pointers to arrays in their explicit form:

#include <stdio.h>

void foo(int (*p)[5])
{
    /* 
        Note that sizeof won't work here without a pointer to an array
        because we need the size of the whole array object, not just a pointer.
    */
    for (int i = 0; i < sizeof *p / sizeof **p; i++)
    {
        printf("%d ", (*p)[i]);
    }

    putchar('\n');
}

int main(void)
{
    int a[] = {1, 2, 3, 4, 5};
    int (*pa)[5] = &a;

    foo(pa);

    return 0;
}

You can also probably guess why they're not often used: the syntax for declaring and dereferencing a pointer to an array is...awkward.

But I think the part of my explanation that was troubling is mention of pointers to arrays as nested dimensions in a multidimensional array. That was wrong, and I have no excuse. What I intended to write (how it came out the way it did is beyond me) is that a pointer to an array is the type of a multidimensional array in value context. To make matters worse, that fact is pretty much irrelevant to the point I was trying to make about the address-of operator. So you can disregard that part in its entirety.

How embarrassing...

Member Avatar for I_m_rude

hey,
means code written above will not work ? because sizeof will not work as you have said ?
here p is a pointer to an array. so sizeof(*p) is size of complete array ? is this right ?
And,
Will you please tell that when we say &a, then isn't it refer to first element of array ? it is a question in one book. i am not getting it.

means code written above will not work ? because sizeof will not work as you have said ?

It will work, but only because the function parameter is a pointer to an array.

here p is a pointer to an array. so sizeof(*p) is size of complete array ? is this right ?

Yes, that's it exactly.

Will you please tell that when we say &a, then isn't it refer to first element of array ? it is a question in one book. i am not getting it.

This is where people tend to get confuzzled. The address is the same, but the type is different. So for int a[5];, a gives you a pointer to int and &a[0] also gives you a pointer to int, because both of these are value context expressions on the array. &a is an object context expression on the array, so the result, even though you get exactly the same address, has a different type: int(*)[5].

Note that this is why the following call to scanf() is buggy:

char name[50];
scanf("%49s", &name); /* The ampersand shouldn't be there! */

The reason why it's buggy is because scanf() is being passed a pointer to an unexpected type. scanf() expects char*, but what's actually passed is char(*)[50].

Member Avatar for I_m_rude

WOW! how great your explainations are! Just one last question which you haven't answered is that &a will give me a pointer to an array, that's right ok. so this tells me that it doesn't refer to first element of array or I should say that it is not giving us address of first element of array , rather giving us address of an array of a particular size ? am i right ? and secondly, when we write

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

where a is integer array and character array respectively. So this means these statement will give wrong result(means it will not take input properly) if i write this ?

so this tells me that it doesn't refer to first element of array or I should say that it is not giving us address of first element of array , rather giving us address of an array of a particular size ? am i right ?

This is where people often get confused. The address of the array is the same as the address of the first element. The difference between a pointer to an array and a pointer to the first element is how that address is interpreted through the data type.

Later down the road you can use this concept to your advantage through a technique called type punning.

So this means these statement will give wrong result

It's not that it won't work as expect, but that's a possibility. Passing a type that's unexpected to scanf() or printf() will invoke undefined behavior. At that point, anything at all could happen, which includes working as expected.

My biggest issue in the past with correcting this error has been the "it works for me" logical fallacy. I'll say that the code is buggy, and the author will respond with "but it works for me".

Member Avatar for I_m_rude

thanks for solving this thread. you are GOD of this language. hats off to u....

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.