question on 2D arrays using pointers

Discussion in 'C Programming' started by Durango2008, May 21, 2009.

  1. Durango2008

    Durango2008 Guest

    Hello,
    I know some C but still learning pointers and I have a question regarding
    arrays using pointers.

    I compiled the following code but I am confused by it:

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

    int main()
    {
    int **a;
    char **b;
    int i;
    a = malloc(2 * sizeof(int *));
    for(i = 0; i < 2; i++)
    a = malloc(13 * sizeof(int));

    b = malloc(2 * sizeof(char *));
    for(i = 0; i < 5; i++)
    b = malloc(13 * sizeof(char));

    a[0][0] = 44;
    b[0][0] = 55;
    printf("a[0][0] = %d\n",a[0][0]);
    printf("(int)*(a) = %d\n", (int)*(a+4));
    printf("b[0][0] = %d\n",b[0][0]);
    printf("(char)*(b) = %d\n", (int)*(b+4));

    return 0;
    }

    I compiled this in both Linux(Redhat) using GCC and Windows XP using
    Code::Blocks.
    In Linux it gave the following results:
    a[0][0] = 44
    (int)*(a) = 44
    b[0][0] = 55
    b[0][0] = 55

    My first question is why do you need to add 4 to the pointer index to get
    the correct result?

    In Windows XP it gave the following results:
    a[0][0] = 44
    (int)*(a) = 44
    b[0][0] = 55
    (char)*(b) = 4079600

    It clearly shows that the final value is wrong and pointer reference issue.

    What I need to know is how can dereference this 2D array properly and what
    are some easier ways of obtaining
    the value of a 2D array using pointers without using indexing?

    Thank you for your help.
     
    Durango2008, May 21, 2009
    #1
    1. Advertising

  2. Durango2008

    myx Guest

    I've tried to compile this code, and (int)*(a+4) really contains value
    of a first element in this 2d array. It's just an strange trick, that
    will not work if you create, for example, a 5x13 array, so that the
    fifth cell after the address, contained in "a" will not contain a
    value of the first element, but will contain an address of the fifth
    row in a 2d array.
     
    myx, May 21, 2009
    #2
    1. Advertising

  3. Durango2008

    Alan Curry Guest

    In article <MD8Rl.29661$>,
    Durango2008 <0m> wrote:
    >
    >"Richard Heathfield" <> wrote in message
    >news:...
    >> Durango2008 said:
    >>> int **a;
    >>> char **b;
    >>> int i;
    >>> a = malloc(2 * sizeof(int *));
    >>> for(i = 0; i < 2; i++)
    >>> a = malloc(13 * sizeof(int));

    ....
    >>> a[0][0] = 44;
    >>> b[0][0] = 55;
    >>> printf("a[0][0] = %d\n",a[0][0]);
    >>> printf("(int)*(a) = %d\n", (int)*(a+4));

    >>
    >> a (which is a lousy name for an object - why do people do that?) is
    >> an int **. a+4 is an expression that points to the int * that is
    >> four int *s along from a.


    And since there are only 2 int *'s at the location indicated by a, adding 4
    is going beyond the end of the malloc'ed object.

    >The correct value from the array a is 44 and for array b is 55.
    >The result displays this but I am not sure why I have to use the (a+4)
    >expression to get this value to display?


    a[0] and a[1] exist, so you can add 0 or 1 to a and get a valid pointer.
    (You can also add 2 to a, and get a special "trailing edge of the object"
    pointer, which isn't good for anything except comparisons to the others.)

    Aside from 0, 1, and 2, no other values may be legally added to a. You get
    a wild pointer, which can point to anything, or could crash the program.

    You somehow found the value 4 which made the wild pointer land on the number
    44. That was just dumb luck. It's not very surprising that this magical value
    would exist, and that it would be a small integer. That just means your first
    2 mallocs returned a couple of close-together memory areas, and when you ran
    past the end of the first one you ended up near the beginning of the second
    one. The partial success of your method doesn't make it any less wrong. You
    can't expect any consistent results from smashing past the end of an array.

    >I am trying to obtain the value 44 that I assigned the first element of
    >array a.


    The thing you're starting with (a) is a pointer to a pointer. The thing
    you're trying to get to (44) is not a pointer at all. Any way you choose to
    get from here to there will involve 2 dereferencing operations, each of which
    removes a level of pointerness. When you use a[0][0] the 2 sets of brackets
    are doing the dereferencing. If you want to use *'s instead of brackets,
    you'll need 2 of those also.

    like this:
    printf("**a = %d\n", **a);

    You could also use 1 pair of brackets and 1 *. All of these are equivalent:
    printf("*a[0] = %d\n", *a[0]);
    printf("(*a)[0] = %d\n", (*a)[0]);
    printf("*(a[0]) = %d\n", *(a[0]));

    If you want addition to be explicitly involved, add 0 anywhere you like!
    printf("*(*(a+0)+0) = %d\n", *(*(a+0)+0));
    printf("(*(a+0))[0] = %d\n", (*(a+0))[0]);
    printf("*(a[0]+0) = %d\n", *(a[0]+0));

    If you add your 0's in the right places, you can easily adjust the expression
    to be equivalent to a[1][2] instea of a[0][0]:
    a[1][2] = 99;
    printf("*(*(a+1)+2) = %d\n", *(*(a+1)+2));
    printf("(*(a+1))[2] = %d\n", (*(a+1))[2]);
    printf("*(a[1]+2) = %d\n", *(a[1]+2));

    By now maybe you see why we usually prefer to just use the brackets. The
    alternatives get ugly fast.

    --
    Alan Curry
     
    Alan Curry, May 21, 2009
    #3
  4. Durango2008

    Durango2008 Guest

    "Richard Heathfield" <> wrote in message
    news:...
    > Durango2008 said:
    >
    > a[0][0] is the way to do it.

    I understand this but the problem is I have to do this without using
    indexing.
    It is an assignment in the book I am following and it specifically asks not
    to use indexing
    to get the value.

    thank you.
     
    Durango2008, May 21, 2009
    #4
  5. Durango2008

    jameskuyper Guest

    Durango2008 wrote:
    > "Richard Heathfield" <> wrote in message
    > news:...
    > > Durango2008 said:
    > >
    > > a[0][0] is the way to do it.

    > I understand this but the problem is I have to do this without using
    > indexing.
    > It is an assignment in the book I am following and it specifically asks not
    > to use indexing
    > to get the value.


    You need to understand exactly what indexing means. I won't solve the
    problem for you, but any decent C text book should tell you that a
    is exactly equivalent to another expression that doesn't involve any
    subscripts. Apply that rule twice to a[0][0], and if you do it
    correctly you'll have your answer. Usually, it's the "correctly" part
    that bogs people down.
     
    jameskuyper, May 21, 2009
    #5
  6. "Durango2008" <0m> writes:
    > I know some C but still learning pointers and I have a question regarding
    > arrays using pointers.

    [snip]

    Others have given you some good advice, but I don't think anyone has
    mentioned section 6 of the comp.lang.c FAQ, <http://www.c-faq.com>.
    So I'll mention it. It's an excellent resource for this kind of
    thing.

    It's also fairly important to keep the terminology straight. In C, a
    two-dimensional array is, strictly speaking, simply an array of arrays
    (and likewise for higher dimensions). What you're building isn't
    really a 2D array; it's an array of pointers, where each pointer
    points to the first element of an array (of char or of int).

    On the other hand, referring to such a data structure as a 2D array is
    common, and I wouldn't say it's actually wrong as long as you keep the
    distinction in mind. An array-of-pointers implementation like yours
    is actually much more flexible than an array of arrays; for example,
    you can adjust the size of each row and of the entire array
    dynamically.

    Confusingly, you can use the same indexing notation in either case.
    Consider this demo program:

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

    int main(void)
    {
    /*
    * First, we create and initialize a simple 2D array.
    * This is very straightforward, but it's inflexible;
    * we have to choose the size when we write the program,
    * and we can't change it later. (C99's VLAs add some
    * flexibility, but at a cost.)
    */
    int arr[2][2] = {{10, 20},
    {30, 40}};

    /*
    * Now we create and initialize a data structure that acts
    * like a 2D array, though strictly speaking it isn't one.
    * This is more work, but it's much more flexible. We can
    * even have different lengths for different rows if
    * we like. (It would be even more work if we kept track
    * of all the sizes rather than assuming it's 2 by 2.)
    */
    int **ptr;
    int i, j;

    ptr = malloc(2 * sizeof *ptr);
    if (ptr == NULL) exit(EXIT_FAILURE);

    for (i = 0; i < 2; i ++) {
    ptr = malloc(2 * sizeof *ptr);
    if (ptr == NULL) exit(EXIT_FAILURE);
    }
    /*
    * Now we initialize the elements (we can't use an
    * initializer for this as we did for arr).
    */
    ptr[0][0] = 100;
    ptr[0][1] = 200;
    ptr[1][0] = 300;
    ptr[1][1] = 400;

    /*
    * Now we can look at the values. Note that we use
    * the same notation for both, but it's not doing the
    * same thing.
    */
    for (i = 0; i < 2; i ++) {
    for (j = 0; j < 2; j ++) {
    printf("arr[%d][%d] = %d, ptr[%d][%d] = %d\n",
    i, j, arr[j],
    i, j, ptr[j]);
    }
    }

    return 0;
    }

    arr[j] and ptr[j] mean very different things, even though they
    look equivalent. The reason for this is that the [] operator really
    takes a pointer as its first operand (pointer[index]). If you give it
    an array rather than a pointer, the array is implicitly converted to a
    pointer; there are two such conversions in arr[j]. If you give
    something that's already a pointer, as in ptr[j], no such
    conversion is necessary. (You can even have hybrid data structures,
    so there are 4 possible interpretations for foo[j], and 8 for
    foo[j][k].)

    And the point all that looping, mallocing, and assigning we did to set
    up ptr was to make ptr[j] work just like arr[j], even though
    they do very different things.

    (Since somebody will mention it if I don't, I am deliberately ignoring
    the possiblity of writing index[pointer] or index[array]; see question
    6.11 in the FAQ for an example of code not to write.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, May 21, 2009
    #6
  7. Durango2008

    Durango2008 Guest

    "Richard Heathfield" <> wrote in message
    news:...
    > X[Y] is precisely equivalent to *(X + Y).
    >
    > X[Y][Z] is precisely equivalent to (X[Y])[Z]
    >
    > So X[Y][Z] is precisely equivalent to *((*(X + Y))+Z)


    Thanks for this clarification, I realize I was doing it wrong but getting
    the value that I was expecting
    threw me off and got me confused. Anyway, thank you again :)
     
    Durango2008, May 22, 2009
    #7
  8. Durango2008

    Durango2008 Guest

    Thanks to everyone who took time to help me out, I am now a bit more
    informed on the nature of pointers.
    I'll probably be back with more newbie questions in the future :p
     
    Durango2008, May 22, 2009
    #8
  9. Durango2008

    Phil Carmody Guest

    (blargg) writes:
    > "Richard Heathfield" wrote:
    >> X[Y] is precisely equivalent to *(X + Y).
    >>
    >> X[Y][Z] is precisely equivalent to (X[Y])[Z]
    >>
    >> So X[Y][Z] is precisely equivalent to *((*(X + Y))+Z)

    >
    > So a[i >> 5] is precisely equivalent to *(a + i >> 5)? I think you need
    > some parenthesis if you're going to say "precisely":


    You're thinking along the lines of textual replacement.
    I'm sure Richard was not viewing it at such a shallow
    level.

    > X[Y] is equivalent to (*((X) + (Y)))


    As a sequence of tokens to be parsed, yes. My presumption
    would be that if you're already processing the semantics
    of X[Y] you've already parsed those two subexpressions.

    Phil
    --
    Marijuana is indeed a dangerous drug.
    It causes governments to wage war against their own people.
    -- Dave Seaman (sci.math, 19 Mar 2009)
     
    Phil Carmody, May 23, 2009
    #9
  10. Durango2008 writes:
    > I know some C but still learning pointers and I have a question regarding
    > arrays using pointers.


    Technically, arrays don't *use* anything. Have you read the FAQ?

    (Please don't use the wrong year in your posting ID.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, May 29, 2009
    #10
  11. Fake-Thompson wrote:
    >Durango2008 [snip]
    >
    >(Please don't use the wrong year in your posting ID.)


    HA!

    -Beej
     
    Beej Jorgensen, May 29, 2009
    #11
  12. Durango2008

    Richard Bos Guest

    Beej Jorgensen <> wrote:

    > Fake-Thompson wrote:
    > >Durango2008 [snip]
    > >
    > >(Please don't use the wrong year in your posting ID.)

    >
    > HA!


    YHBT.

    Richard
     
    Richard Bos, May 30, 2009
    #12
  13. Richard Bos <> wrote:
    >YHBT.


    I identified the troll, and then laughed at what he said. Now I've been
    to Amsterdam, and I know at least the customs officers have a sense of
    humor.

    -Beej
     
    Beej Jorgensen, May 30, 2009
    #13
  14. Durango2008

    Flash Gordon Guest

    Beej Jorgensen wrote:
    > Richard Bos <> wrote:
    >> YHBT.

    >
    > I identified the troll, and then laughed at what he said. Now I've been
    > to Amsterdam, and I know at least the customs officers have a sense of
    > humor.


    Ah, so you think it is appropriate to encourage trolling.
    --
    Flash Gordon
     
    Flash Gordon, May 30, 2009
    #14
  15. Flash Gordon <> wrote:
    >Ah, so you think it is appropriate to encourage trolling.


    HA! You won't get me that easily!

    -Beej
     
    Beej Jorgensen, May 30, 2009
    #15
    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. kelvSYC

    Arrays and Pointers to Arrays

    kelvSYC, Sep 26, 2003, in forum: C Programming
    Replies:
    2
    Views:
    390
  2. Replies:
    1
    Views:
    663
    -berlin.de
    Mar 28, 2005
  3. Philipp
    Replies:
    21
    Views:
    1,157
    Philipp
    Jan 20, 2009
  4. Francesco
    Replies:
    2
    Views:
    1,127
    Francesco
    Nov 6, 2009
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    695
Loading...

Share This Page