Two dimentional array dereference in C

Discussion in 'C Programming' started by Srinu, Nov 19, 2007.

  1. Srinu

    Srinu Guest

    Hi All,

    We know the following facts,

    1. A two dimentional arrays in C is stored similar to a single
    dimentional array.
    2. * is the dereference operator that gives value at address denoted
    by the operand to this operator. i.e *p is the value at address given
    by p.
    3. In case of two dimentional array a[][], a+1 refers to the second
    row, and a+3 refers to the fourth row.
    4. *(derefernce) operator has higher precedence that + operator.

    So lets look at the following program...

    1 #include<stdio.h>
    2 int main()
    3 {
    4 int p[5][5];
    5 p[0][0]=4;
    6 p[2][0]=5;
    7 p[2][3]=6;
    8 printf("\n%d", *(*(p+2)+3));
    9 printf("\n%d", *(*(p+2)));
    10 printf("\n%d", *(*p+0));
    11 }


    Out put of this program compiled in gcc 3.4.2 is

    6
    5
    4

    Discussion on line number 8 :
    -------------------------------------------
    In expression *(*(p+2)+3)), p is the base address and points to p[0]
    [0]; according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].
    According to fact 2, * operator on this should give the value at
    address denoted by p[2][0], so *(p+2) should be 5; then again +3, that
    is, total is 8 and the first * on this...so it should not give the
    appropriate result.

    But it gives !

    So, what is that second * in the expression *(*(p+2)+3)) doing?
    Does the meaning of this second * is "value at..." or something else?

    [The other two lines numbered 9, 10 in the program is just for
    reference]

    With regards.
    Srinu
    Srinu, Nov 19, 2007
    #1
    1. Advertising

  2. Srinu

    Dimuthu Guest

    On Nov 19, 12:01 pm, Srinu <> wrote:
    > Hi All,
    >
    > We know the following facts,
    >
    > 1. A two dimentional arrays in C is stored similar to a single
    > dimentional array.
    > 2. * is the dereference operator that gives value at address denoted
    > by the operand to this operator. i.e *p is the value at address given
    > by p.
    > 3. In case of two dimentional array a[][], a+1 refers to the second
    > row, and a+3 refers to the fourth row.
    > 4. *(derefernce) operator has higher precedence that + operator.
    >
    > So lets look at the following program...
    >
    > 1 #include<stdio.h>
    > 2 int main()
    > 3 {
    > 4 int p[5][5];
    > 5 p[0][0]=4;
    > 6 p[2][0]=5;
    > 7 p[2][3]=6;
    > 8 printf("\n%d", *(*(p+2)+3));
    > 9 printf("\n%d", *(*(p+2)));
    > 10 printf("\n%d", *(*p+0));
    > 11 }
    >
    > Out put of this program compiled in gcc 3.4.2 is
    >
    > 6
    > 5
    > 4
    >
    > Discussion on line number 8 :
    > -------------------------------------------
    > In expression *(*(p+2)+3)), p is the base address and points to p[0]
    > [0]; according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].
    > According to fact 2, * operator on this should give the value at
    > address denoted by p[2][0], so *(p+2) should be 5; then again +3, that
    > is, total is 8 and the first * on this...so it should not give the
    > appropriate result.
    >
    > But it gives !
    >
    > So, what is that second * in the expression *(*(p+2)+3)) doing?
    > Does the meaning of this second * is "value at..." or something else?
    >
    > [The other two lines numbered 9, 10 in the program is just for
    > reference]
    >
    > With regards.
    > Srinu


    Hi Srinu,

    Did you check what are the values of the memory pointers, I check it
    with gdb and it was like following.
    For clarity I m showing only the last two digits

    p 0x00

    *p 0x00
    *p+1 0x04
    *p+2 0x08
    *p+3 0x0c
    *p+4 0xa0

    p+1 0xa4 ( == *p +5 )

    *(p+1) 0xa4
    *(p+1)+1 0xa8
    *(p+1)+2 0xac
    *(p+1)+3 0xb0
    *(p+1)+4 0xb4

    p+2 0xb8

    *(p+2) 0xb8
    *(p+2)+1 0xbc
    *(p+2)+2 0xc0
    *(p+2)+3 0xc4
    *(p+2)+4 0xc8
    and so on.


    So as you said the 2-D array is stored as a 1-D array in the memory
    space. But the fact is when it is accessing through referencing it
    shows the following behaviors.

    when we say (p + 1), actually we are increasing the p memory pointer
    with (5 * sizeof(int)) , that is the compiler keeps p as a pointer of
    2-D array.

    when we say (*p +1), actually we are increasing *p by sizeof(int),
    that is *p is like a pointer of 1-D array.

    and p, p+1, p +2, .. p+4 points to the value which is same as their
    address,
    i.e. *p == p and *(p+1) == (p+1) like that.

    but *p = p here doesn't imply **p = *p, because here **p = p[0][0],

    I think this is a trick whenever you want to access p[x][y] from p
    which is declared as int p[n][m] the following operation.

    *(*(p+x)+y) works.

    And whenever i want to allocate 2-D array dynamically,
    I can declare the memeory space like in the following, (Here memory is
    not a 1-D array)

    int **p = (int**)malloc(sizeof(int*)*n);
    int i;
    for(i = 0; i < n; i ++)
    {
    p = (int*)malloc(sizeof(int)*m);
    }

    Still I can use p[x][y] to access the exact content, because it is
    interpreted as *(*(p+x)+y).


    So I think the behavior you were talking about is a hack in c. If
    there is some better logical explanation to this, Please correct me.


    Thanks
    Dimuthu
    Dimuthu, Nov 19, 2007
    #2
    1. Advertising

  3. Srinu

    James Kuyper Guest

    Srinu wrote:
    > Hi All,
    >
    > We know the following facts,
    >
    > 1. A two dimentional arrays in C is stored similar to a single
    > dimentional array.
    > 2. * is the dereference operator that gives value at address denoted
    > by the operand to this operator. i.e *p is the value at address given
    > by p.
    > 3. In case of two dimentional array a[][], a+1 refers to the second
    > row, and a+3 refers to the fourth row.
    > 4. *(derefernce) operator has higher precedence that + operator.
    >
    > So lets look at the following program...
    >
    > 1 #include<stdio.h>
    > 2 int main()
    > 3 {
    > 4 int p[5][5];
    > 5 p[0][0]=4;
    > 6 p[2][0]=5;
    > 7 p[2][3]=6;
    > 8 printf("\n%d", *(*(p+2)+3));


    *(p+2) means exactly the same thing as p[2]. *(p[2]+3) means exactly the
    same thing as p[2][3]. Therefore, this should print out 6.

    > 9 printf("\n%d", *(*(p+2)));


    Same as p[2][0]

    > 10 printf("\n%d", *(*p+0));


    Same as p[0][0]

    > 11 }
    >
    >
    > Out put of this program compiled in gcc 3.4.2 is
    >
    > 6
    > 5
    > 4


    Exactly as expected.

    >
    > Discussion on line number 8 :
    > -------------------------------------------
    > In expression *(*(p+2)+3)), p is the base address and points to p[0]
    > [0]; according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].


    One of the subtle details about C is the fact that it doesn't really
    have multi-dimensional arrays. What it has is one-dimensional arrays
    whose element type can also be an array. The array p contains 5 elements
    (not 25). Each of those elements is itself an array of 5 ints. That
    distinction may seem like sheer pedanticism, but understanding it is
    essential to understanding some features of C, as your question
    demonstrates.

    In this context, as in many others, an array decays into a pointer to
    it's own first element, which is p[0], an array containing 5 ints.
    Therefore, p+2 points at p[2], another array containing 5 ints.

    > According to fact 2, * operator on this should give the value at
    > address denoted by p[2][0], so *(p+2) should be 5; then again +3, that


    When you apply the dereferencing operator '*' to a pointer, you get a
    value of the type that is pointed at. p+2 has the type "pointer to an
    array of 5 ints". Therefore, when you dereference it, you don't get an
    int, you get an array of 5 ints. In this context, that array decays into
    a pointer to it's first element, which is p[2][0]. Therefore, when you
    add 3 to it, you get a pointer to it's fourth element, p[2][3].
    Dereferencing that pointer gives the value you stored in that location,
    which was 6.

    > is, total is 8 and the first * on this...so it should not give the


    If you had been correct, the number 8 would not have been something you
    could safely apply the * operator to.

    > appropriate result.
    >
    > But it gives !
    >
    > So, what is that second * in the expression *(*(p+2)+3)) doing?
    > Does the meaning of this second * is "value at..." or something else?


    Yes, it means the value at the location pointed at by it's right
    operand, in this case *(p+2)+3. That expression points at p[2][3], so
    *(*(p+2)+3) is p[2][3].
    James Kuyper, Nov 19, 2007
    #3
  4. Srinu

    Chris Torek Guest

    In article <>
    Srinu <> wrote:
    [snippage]
    > 4 int p[5][5];

    [snippage]
    > 8 printf("\n%d", *(*(p+2)+3));
    >Discussion on line number 8 :
    >-------------------------------------------
    >In expression *(*(p+2)+3)), p is the base address


    Yes ...

    >and points to p[0][0];


    Sort of, but not quite. The "value" of p (p when converted from
    lvalue, or "object", to value) is a pointer value, pointing to the
    first element of the array "p", i.e., the entire first row. In
    that sense, "the value of p" points not to p[0][0] alone, but rather
    to *five* "int"s p[0][0], p[0][1], p[0][2], p[0][3], and p[0][4],
    all simultaneously. See also <http://web.torek.net/torek/c/pa.html>.

    >according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].


    Here, p+2 is definitely a value, not an object, so we need not
    worry about the distinction between objects ("lvalues") and values.

    Again, it refers to the *entire* row -- not *just* p[2][0], but
    rather all five array elements p[2][0] through p[2][4] inclusive.
    It is only once you follow this pointer value to the entire array, then
    convert this array to a value, that it stops referring to the entire
    row, and starts referring only to the single int p[2][0].
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Nov 19, 2007
    #4
  5. On Sun, 18 Nov 2007 23:01:48 -0800 (PST), Srinu
    <> wrote:

    >Hi All,
    >
    >We know the following facts,
    >
    >1. A two dimentional arrays in C is stored similar to a single
    >dimentional array.


    For some meaning of the word similar.

    >2. * is the dereference operator that gives value at address denoted
    >by the operand to this operator. i.e *p is the value at address given
    >by p.


    Sometimes the value is an aggregate.

    >3. In case of two dimentional array a[][], a+1 refers to the second
    >row, and a+3 refers to the fourth row.


    For some meaning of refers.

    >4. *(derefernce) operator has higher precedence that + operator.
    >
    >So lets look at the following program...
    >
    > 1 #include<stdio.h>
    > 2 int main()
    > 3 {
    > 4 int p[5][5];
    > 5 p[0][0]=4;
    > 6 p[2][0]=5;
    > 7 p[2][3]=6;
    > 8 printf("\n%d", *(*(p+2)+3));
    > 9 printf("\n%d", *(*(p+2)));
    > 10 printf("\n%d", *(*p+0));
    > 11 }
    >
    >
    >Out put of this program compiled in gcc 3.4.2 is
    >
    >6
    >5
    >4
    >
    >Discussion on line number 8 :
    >-------------------------------------------
    >In expression *(*(p+2)+3)), p is the base address and points to p[0]


    p is an array. It is not an address nor is it a pointer.

    >[0]; according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].


    Except for three conditions which don't apply, an expression with
    array type is converted to the address of the first element with type
    pointer to element type. In this case p converts to the address of
    p[0] with type pointer to array of 5 int. This happens to be the same
    address as &p[0][0] but a completely different type.

    p+2 points to the third row. *(p+2) IS the third row. *(p+2)+3
    points to the fourth element of that row. *(*(p+2)+3) is that
    element.

    >According to fact 2, * operator on this should give the value at
    >address denoted by p[2][0], so *(p+2) should be 5; then again +3, that


    No! According to fact 2, *(p+2) should evaluate to the entire array
    p[2]. In fact, there is a statement in the standard that says p is
    identical to *(p+i) (which is also identical to *(i+p) which is in
    turn identical to i[p]).

    >is, total is 8 and the first * on this...so it should not give the


    No, the +3 merely moves you along to the address of the fourth element
    in p[2].

    >appropriate result.
    >
    >But it gives !
    >
    >So, what is that second * in the expression *(*(p+2)+3)) doing?


    Each asterisk in the expression means exactly the same thing each
    time, namely evaluate to the object pointed to.

    >Does the meaning of this second * is "value at..." or something else?
    >
    >[The other two lines numbered 9, 10 in the program is just for
    >reference]



    Remove del for email
    Barry Schwarz, Nov 20, 2007
    #5
  6. Srinu

    somenath Guest

    On Nov 20, 4:15 am, Chris Torek <> wrote:
    > In article <>Srinu <> wrote:
    >
    > [snippage]
    >
    > > 4 int p[5][5];

    > [snippage]
    > > 8 printf("\n%d", *(*(p+2)+3));
    > >Discussion on line number 8 :
    > >-------------------------------------------
    > >In expression *(*(p+2)+3)), p is the base address

    >
    > Yes ...
    >
    > >and points to p[0][0];

    >
    > Sort of, but not quite. The "value" of p (p when converted from
    > lvalue, or "object", to value) is a pointer value, pointing to the
    > first element of the array "p", i.e., the entire first row. In
    > that sense, "the value of p" points not to p[0][0] alone, but rather
    > to *five* "int"s p[0][0], p[0][1], p[0][2], p[0][3], and p[0][4],
    > all simultaneously. See also <http://web.torek.net/torek/c/pa.html>.
    >
    > >according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].

    >
    > Here, p+2 is definitely a value, not an object, so we need not
    > worry about the distinction between objects ("lvalues") and values.
    >
    > Again, it refers to the *entire* row -- not *just* p[2][0], but
    > rather all five array elements p[2][0] through p[2][4] inclusive.
    > It is only once you follow this pointer value to the entire array, then
    > convert this array to a value, that it stops referring to the entire
    > row, and starts referring only to the single int p[2][0].
    > --
    >


    I am just getting confused here.
    If p points to all the 5 element of the first row why the sizeof(p) is
    100 ?
    Where sizeof(int) is 4 ?
    And sizeof(p+2) is equal to 4 ?

    Please look at the program bellow

    #include<stdio.h>
    int main(void)
    {
    int p[5][5];
    printf("\n size of p = %d \n",(int)sizeof(p ));
    printf("\n sizeof p+2 = %d \n",(int)sizeof(p + 2 ));
    return 0;
    }
    Output is


    size of p = 100

    sizeof p+2 = 4
    If p points to the first row will it size not be 5*sizeof(int) ?
    somenath, Nov 20, 2007
    #6
  7. somenath <> writes:

    > On Nov 20, 4:15 am, Chris Torek <> wrote:
    >> In article <>Srinu <> wrote:
    >>
    >> [snippage]
    >>
    >> > 4 int p[5][5];

    <snip>
    >> Sort of, but not quite. The "value" of p (p when converted from
    >> lvalue, or "object", to value) is a pointer value, pointing to the
    >> first element of the array "p", i.e., the entire first row. In
    >> that sense, "the value of p" points not to p[0][0] alone, but rather
    >> to *five* "int"s p[0][0], p[0][1], p[0][2], p[0][3], and p[0][4],
    >> all simultaneously. See also <http://web.torek.net/torek/c/pa.html>.
    >>
    >> >according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].

    >>
    >> Here, p+2 is definitely a value, not an object, so we need not
    >> worry about the distinction between objects ("lvalues") and values.
    >>
    >> Again, it refers to the *entire* row -- not *just* p[2][0], but
    >> rather all five array elements p[2][0] through p[2][4] inclusive.
    >> It is only once you follow this pointer value to the entire array, then
    >> convert this array to a value, that it stops referring to the entire
    >> row, and starts referring only to the single int p[2][0].

    >
    > I am just getting confused here.
    > If p points to all the 5 element of the first row why the sizeof(p) is
    > 100 ?
    > Where sizeof(int) is 4 ?
    > And sizeof(p+2) is equal to 4 ?


    6.3.2.1 p3:

    Except when it is the operand of the sizeof operator or the unary &
    operator, or is a string literal used to initialize an array, an
    expression that has type ‘‘array of type’’ is converted to an
    expression with type ‘‘pointer to type’’ that points to the initial
    element of the array object and is not an lvalue.

    >
    > Please look at the program bellow
    >
    > #include<stdio.h>
    > int main(void)
    > {
    > int p[5][5];
    > printf("\n size of p = %d \n",(int)sizeof(p ));
    > printf("\n sizeof p+2 = %d \n",(int)sizeof(p + 2 ));
    > return 0;
    > }
    > Output is
    >
    >
    > size of p = 100
    >
    > sizeof p+2 = 4


    'sizeof p' gives the size of the array 'p' -- the conversion to
    pointer does not happen when the expression is the operand of sizeof.

    The expression 'p + 2' first involves converting p to a pointer to an
    array of 5 ints. Adding 2 has no effect on the type -- the type of
    the expression 'p + 2' is still a pointer type not an array type.
    Applying sizeof has no special effect here -- the operand does not
    have an array type.

    --
    Ben.
    Ben Bacarisse, Nov 20, 2007
    #7
  8. Srinu

    James Kuyper Guest

    somenath wrote:
    ....
    > I am just getting confused here.
    > If p points to all the 5 element of the first row why the sizeof(p) is
    > 100 ?


    6.3.2.1p3:
    "Except when it is the operand of the sizeof operator or the unary &
    operator, or is a string literal used to initialize an array, an
    expression that has type ‘‘array of type’’ is converted to an expression
    with type ‘‘pointer to type’’ that points to the initial element of
    the array object and is not an lvalue."

    This conversion is commonly referred to as "decaying". It doesn't happen
    in sizeof(p), but it does happen in p[2] and in *(p+2), both of which
    mean exactly the same thing.

    > Where sizeof(int) is 4 ?
    > And sizeof(p+2) is equal to 4 ?


    As indicated above, in an additive expression like p+2, p decays to a
    pointer type. This is not covered by the exception for the sizeof
    operator mentioned above, because that exception only applies when the
    operand of sizeof has an array type. The operand is p+2, not p, and p+2
    has a pointer type.
    James Kuyper, Nov 20, 2007
    #8
  9. Srinu

    Chris Torek Guest

    [We are given an array object named "p" -- which is not the best
    name for an array, but never mind that :) -- where p has type
    (int [5][5]).]

    >On Nov 20, 4:15 am, Chris Torek <> wrote:
    >>... The "value" of p (p when converted from lvalue, or "object",

    >to value) is a pointer value, pointing to the first element of the
    >>array "p", i.e., the entire first row. ...


    In article <>
    somenath <> wrote:
    >I am just getting confused here.
    >If p points to all the 5 element of the first row why the sizeof(p) is
    >100 ?


    The sizeof operator suppresses object-to-value conversion.

    In *most*, but definitely NOT all, contexts, an object of type
    "array N of T" becomes a value of type "pointer to T", where N
    is the size of the array and T is the type of the array elements.
    In this case, N is 5, and T is (int [5]), or "array 5 of int".

    The sizeof operator is one of those exceptions. The unary "&"
    (address-of) operator is another. In both cases, applying these
    operators to an array leaves the array as an array, and finds the
    size of the array, or the address of the array, respectively.

    The size of the array "p" is the size of 5 arrays of 5 arrays of
    "int". If sizeof(int) == 4:

    >Where sizeof(int) is 4 ?


    then (sizeof p) is 100 (5 * 5 * 4).

    >And sizeof(p+2) is equal to 4 ?


    In this case, the operand of sizeof is p+2 -- not p -- so the
    binary "+" operator gets the first crack at things. The binary
    + operator is one of the usual cases (remember, sizeof is one of
    the UN-usual cases), so that we go from array object to pointer
    value. Here we get the "value" of p, via The Rule about arrays
    and pointers in C, so we have a pointer to the entire first row
    of the array "p" (i.e., all of p[0]). The binary + operator moves
    forward two rows, giving a pointer of type "int (*)[5]", pointing
    to the third row of the array "p" (i.e., all of p[2]).

    The sizeof operator thus has, as its operand, a value of type
    "pointer to array 5 of int" (int (*)[5]); the size of such a pointer
    is up to the compiler and/or machine, and in your case, is 4. (On
    some machines this pointer has size 2 or 8; on a few, it even has
    size 1. For instance, some DSP C compilers have 32-bit "C bytes".)

    For additional illustration and/or confusion, try:

    sizeof (&p)
    sizeof (int (*)[5][5]) /* same as sizeof &p */

    sizeof (int [5][5]) /* same as sizeof p */

    sizeof (int (*)[5]) /* same as sizeof (p+0) or sizeof (p+i) */

    sizeof (p[0])
    sizeof (*p) /* same as sizeof p[0] */
    sizeof (int [5]) /* same as sizeof p[0] */

    The binding of the various operators is such that you can write
    "sizeof &p" or "sizeof p[0]" without parentheses; however, note
    that "sizeof (p + 0)" differs from "sizeof p + 0" because the
    latter parses the same as "(sizeof p) + 0".

    All of this makes more sense mentally, at least to me, if you
    rewrite all your use of "p" (and this article) to use the name
    "arr" instead.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Nov 20, 2007
    #9
  10. On Mon, 19 Nov 2007 04:25:27 -0800 (PST), Dimuthu <>
    wrote:

    >On Nov 19, 12:01 pm, Srinu <> wrote:
    >> Hi All,
    >>
    >> We know the following facts,
    >>
    >> 1. A two dimentional arrays in C is stored similar to a single
    >> dimentional array.
    >> 2. * is the dereference operator that gives value at address denoted
    >> by the operand to this operator. i.e *p is the value at address given
    >> by p.
    >> 3. In case of two dimentional array a[][], a+1 refers to the second
    >> row, and a+3 refers to the fourth row.
    >> 4. *(derefernce) operator has higher precedence that + operator.
    >>
    >> So lets look at the following program...
    >>
    >> 1 #include<stdio.h>
    >> 2 int main()
    >> 3 {
    >> 4 int p[5][5];
    >> 5 p[0][0]=4;
    >> 6 p[2][0]=5;
    >> 7 p[2][3]=6;
    >> 8 printf("\n%d", *(*(p+2)+3));
    >> 9 printf("\n%d", *(*(p+2)));
    >> 10 printf("\n%d", *(*p+0));
    >> 11 }
    >>
    >> Out put of this program compiled in gcc 3.4.2 is
    >>
    >> 6
    >> 5
    >> 4
    >>
    >> Discussion on line number 8 :
    >> -------------------------------------------
    >> In expression *(*(p+2)+3)), p is the base address and points to p[0]
    >> [0]; according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].
    >> According to fact 2, * operator on this should give the value at
    >> address denoted by p[2][0], so *(p+2) should be 5; then again +3, that
    >> is, total is 8 and the first * on this...so it should not give the
    >> appropriate result.
    >>
    >> But it gives !
    >>
    >> So, what is that second * in the expression *(*(p+2)+3)) doing?
    >> Does the meaning of this second * is "value at..." or something else?
    >>
    >> [The other two lines numbered 9, 10 in the program is just for
    >> reference]
    >>
    >> With regards.
    >> Srinu

    >
    >Hi Srinu,
    >
    >Did you check what are the values of the memory pointers, I check it
    >with gdb and it was like following.
    >For clarity I m showing only the last two digits
    >
    >p 0x00
    >
    > *p 0x00


    This makes no sense. *p is the same as p[0] and is an array of 5 int.
    Which last two digits do you think you are showing, especially since
    you only show one byte?

    > *p+1 0x04
    > *p+2 0x08


    *p is an array. In this context, it is converted to a pointer to the
    first element, &p[0][0]. Adding 2 to this address produces the
    address of p[0][2]. What you are displaying is the low order byte of
    the address.

    > *p+3 0x0c
    > *p+4 0xa0


    Up to this point, it appeared that sizeof(int) was 4 on your system.
    This value of 0xa0 appears inconsistent.

    >
    >p+1 0xa4 ( == *p +5 )


    The expression p+1 has type pointer to array of 5 int. The expression
    *p+5 has type pointer to int. Even if they evaluate to the same
    address, they are hardly equal.

    >
    > *(p+1) 0xa4


    *(p+1) is by definition equivalent to p[1], which is an array of 5
    int.

    > *(p+1)+1 0xa8
    > *(p+1)+2 0xac
    > *(p+1)+3 0xb0
    > *(p+1)+4 0xb4


    Since these are the addresses of p[1][1], p[1][2], p[1][3]and p[1][4],
    the constant increment of 4 makes sense.

    >
    >p+2 0xb8
    >
    > *(p+2) 0xb8
    > *(p+2)+1 0xbc
    > *(p+2)+2 0xc0
    > *(p+2)+3 0xc4
    > *(p+2)+4 0xc8
    > and so on.
    >
    >
    >So as you said the 2-D array is stored as a 1-D array in the memory
    >space. But the fact is when it is accessing through referencing it


    It is stored as an array of arrays.

    >shows the following behaviors.
    >
    >when we say (p + 1), actually we are increasing the p memory pointer
    >with (5 * sizeof(int)) , that is the compiler keeps p as a pointer of
    >2-D array.


    p is not a pointer. What does happen is that (except for three
    conditions which don't apply here) any expression of type array is
    converted to a pointer to the first element of the array. In this
    case, p is converted to &p[0] which has type pointer to array of 5
    int.

    >
    >when we say (*p +1), actually we are increasing *p by sizeof(int),
    >that is *p is like a pointer of 1-D array.


    More to the point, *p is an array, namely p[0]. The expression *p is
    converted as described above.

    >
    >and p, p+1, p +2, .. p+4 points to the value which is same as their
    >address,
    >i.e. *p == p and *(p+1) == (p+1) like that.


    It is extremely unlikely that the value pointed to is the same as the
    address.

    >
    >but *p = p here doesn't imply **p = *p, because here **p = p[0][0],


    But *p doesn't equal p either.

    >
    >I think this is a trick whenever you want to access p[x][y] from p
    >which is declared as int p[n][m] the following operation.
    >
    >*(*(p+x)+y) works.


    It's not a trick, it's the definition in the standard.

    >
    >And whenever i want to allocate 2-D array dynamically,
    >I can declare the memeory space like in the following, (Here memory is
    >not a 1-D array)
    >
    >int **p = (int**)malloc(sizeof(int*)*n);


    Don't cast the return from malloc.

    >int i;
    >for(i = 0; i < n; i ++)
    >{
    > p = (int*)malloc(sizeof(int)*m);
    >}
    >
    >Still I can use p[x][y] to access the exact content, because it is
    >interpreted as *(*(p+x)+y).
    >
    >
    >So I think the behavior you were talking about is a hack in c. If
    >there is some better logical explanation to this, Please correct me.


    Standard features of the language are hardly hacks.


    Remove del for email
    Barry Schwarz, Nov 21, 2007
    #10
  11. On Tue, 20 Nov 2007 00:50:39 -0800 (PST), somenath
    <> wrote:

    >On Nov 20, 4:15 am, Chris Torek <> wrote:
    >> In article <>Srinu <> wrote:
    >>
    >> [snippage]
    >>
    >> > 4 int p[5][5];

    >> [snippage]
    >> > 8 printf("\n%d", *(*(p+2)+3));
    >> >Discussion on line number 8 :
    >> >-------------------------------------------
    >> >In expression *(*(p+2)+3)), p is the base address

    >>
    >> Yes ...
    >>
    >> >and points to p[0][0];

    >>
    >> Sort of, but not quite. The "value" of p (p when converted from
    >> lvalue, or "object", to value) is a pointer value, pointing to the
    >> first element of the array "p", i.e., the entire first row. In
    >> that sense, "the value of p" points not to p[0][0] alone, but rather
    >> to *five* "int"s p[0][0], p[0][1], p[0][2], p[0][3], and p[0][4],
    >> all simultaneously. See also <http://web.torek.net/torek/c/pa.html>.
    >>
    >> >according to fact 3, (p+2) refers to third rowof p, i.e. p[2][0].

    >>
    >> Here, p+2 is definitely a value, not an object, so we need not
    >> worry about the distinction between objects ("lvalues") and values.
    >>
    >> Again, it refers to the *entire* row -- not *just* p[2][0], but
    >> rather all five array elements p[2][0] through p[2][4] inclusive.
    >> It is only once you follow this pointer value to the entire array, then
    >> convert this array to a value, that it stops referring to the entire
    >> row, and starts referring only to the single int p[2][0].
    >> --
    >>

    >
    >I am just getting confused here.


    The confusion is between the object p and the expression p.

    >If p points to all the 5 element of the first row why the sizeof(p) is
    >100 ?


    There are three exceptions where an expression of type array is not
    converted to pointer to the first element of the array. One of them
    is when it is the operand of the sizeof operator. Therefore, sizeof p
    refers to the entire array which has 5 elements, each of which
    contains 5 int. Since sizeof(int) is 4, you get 100 for the 25 int
    involved.

    But the expression p, when not covered by an exception, is converted
    to &p[0]. This is the address of the entire array of 5 int. As
    usual, the address refers only to the first byte of the array but
    sizeof p[0] is 20 in this example for the same reason described above.

    >Where sizeof(int) is 4 ?
    >And sizeof(p+2) is equal to 4 ?


    Your compiler is interpreting p+2 is a pointer expression and sizeof
    is evaluating the size of the pointer.

    >
    >Please look at the program bellow
    >
    >#include<stdio.h>
    >int main(void)
    >{
    > int p[5][5];
    > printf("\n size of p = %d \n",(int)sizeof(p ));
    > printf("\n sizeof p+2 = %d \n",(int)sizeof(p + 2 ));
    > return 0;
    >}
    >Output is
    >
    >
    > size of p = 100
    >
    > sizeof p+2 = 4
    >If p points to the first row will it size not be 5*sizeof(int) ?



    Remove del for email
    Barry Schwarz, Nov 21, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Abby
    Replies:
    2
    Views:
    608
  2. ranjmis
    Replies:
    14
    Views:
    519
    Ben C
    Mar 12, 2006
  3. Al
    Replies:
    8
    Views:
    360
    Mark P
    Oct 29, 2005
  4. NvrBst
    Replies:
    3
    Views:
    435
    NvrBst
    Nov 13, 2008
  5. DanchikPU
    Replies:
    7
    Views:
    98
    Uri Guttman
    Jun 21, 2007
Loading...

Share This Page