Two dimensional array Question

Discussion in 'C Programming' started by mdh, May 8, 2008.

  1. mdh

    mdh Guest

    I am still having a problem understanding K&RII on p 112. I have
    looked at the FAQs --which I am sure answer it in a way that I have
    missed, so here goes.
    A 2-dim array, (per K&R) is really a 1-dim array, each of whose
    elements is an array.
    Looking at the debugger I use, arr[2][13] is shown as an initial value
    of "2", but when expanded, there are 2 consecutive arrays of 13
    elements.
    So, may I ask this?
    Is there anything special that marks the end of the first 13 elements
    from the beginning of the 2nd 13 elements? In other words, it seems to
    me that this is nothing more than a 1-dim array, with the information
    about the structure of the array provided by the declaration?
    Hopefully this makes sense.

    The exercise associated with this, used the construct

    *p = arr[1 or 0 ] to point to either the "first" or "second" row of
    the array. Does the compiler "know" where to point to because it has
    been given this information by the declaration of "13" in arr[2][13].
    Hopefully this makes sense too!


    And lastly, K&R's description of "each of whose elements is an array"
    has never made sense to me. It may be that the answer to the above may
    clarify it.

    Thanks in advance.
     
    mdh, May 8, 2008
    #1
    1. Advertising

  2. mdh

    Default User Guest

    Joe Wright wrote:

    > mdh wrote:


    > Perfect sense. All above is correct. Given 'int arr[2][13];', arr is
    > an array 2 of array 13 of int. 26 consecutive ints.
    >
    > > The exercise associated with this, used the construct
    > >
    > > *p = arr[1 or 0 ] to point to either the "first" or "second" row of
    > > the array. Does the compiler "know" where to point to because it has
    > > been given this information by the declaration of "13" in
    > > arr[2][13]. Hopefully this makes sense too!
    > >

    > No. arr[0] is (the address of) an array 13 of int.


    No, it's not. It is an array 13 of int, not a pointer to one. arr is a
    pointer to array 13 of int.

    > The pointer 'p'
    > must be declared to reflect this.
    >
    > int (*p)[13];
    >
    > Now p is a pointer to array 13 of int and..
    >
    > p = arr[0];
    >
    > ..makes sense.


    Not to me.

    p = &arr[0];

    Would. Or what the OP had:

    int *p;
    p = arr[0];





    Brian
     
    Default User, May 9, 2008
    #2
    1. Advertising

  3. mdh <> writes:

    <When discussing int a[2][13];>

    > And lastly, K&R's description of "each of whose elements is an array"
    > has never made sense to me. It may be that the answer to the above may
    > clarify it.


    Another thought... Do you have a problem with:

    struct ints { int a,b,c,d,e,f,g,h,i,j,k,l,m; };
    struct ints a[2];

    being an array, each of whose elements is a structure of 13 ints?
    What if we say:

    struct ints { int e[13]; };
    struct ints a[2];

    For many people the trouble is the way it is written. If it were
    something like: 'int[13] a[2];' they might find it easier to swallow
    but the array declarators group like this:

    int (a[2]) [13] ;

    (you can write that if you want!) so a is "an array of 2... arrays of
    13... ints. I think you are very close to "getting it".

    --
    Ben.
     
    Ben Bacarisse, May 9, 2008
    #3
  4. mdh

    mdh Guest

    Thanks to all who responded. It makes a *little* more sense now, but I
    think it will hopefully clear up with time and practice.
     
    mdh, May 9, 2008
    #4
  5. On Thu, 8 May 2008 08:16:13 -0700 (PDT), mdh <> wrote:

    >I am still having a problem understanding K&RII on p 112. I have
    >looked at the FAQs --which I am sure answer it in a way that I have
    >missed, so here goes.
    >A 2-dim array, (per K&R) is really a 1-dim array, each of whose
    >elements is an array.


    The C99 standard uses the term "multidinensional array" so K&R is
    slightly out of date in this regard.

    >Looking at the debugger I use, arr[2][13] is shown as an initial value
    >of "2", but when expanded, there are 2 consecutive arrays of 13
    >elements.


    What do you mean by "2". Is it an array of char arrays and the first
    of such holds the string '2' '\0'?

    >So, may I ask this?
    >Is there anything special that marks the end of the first 13 elements
    >from the beginning of the 2nd 13 elements? In other words, it seems to


    No. It is prohibited. arr[1] must immediately follow arr[0] in
    memory.

    >me that this is nothing more than a 1-dim array, with the information
    >about the structure of the array provided by the declaration?
    >Hopefully this makes sense.


    It is true that the 26 "basic elements" of arr will appear in memory
    "linearly". This has prompted many debates about whether a pointer to
    arr[0][0] can be used with subscripts ranging from 0 to 25 to access
    all 26. What is not in dispute is that in a 1d array T x[N], x[0]
    evaluates to an element of type T. In your case, arr[0] evaluates to
    an array of T. To my mind, this is sufficient to say arr cannot be
    considered a 1d array.

    >
    >The exercise associated with this, used the construct
    >
    > *p = arr[1 or 0 ] to point to either the "first" or "second" row of
    >the array. Does the compiler "know" where to point to because it has
    >been given this information by the declaration of "13" in arr[2][13].
    >Hopefully this makes sense too!


    Yes and yes.

    >
    >
    >And lastly, K&R's description of "each of whose elements is an array"
    >has never made sense to me. It may be that the answer to the above may
    >clarify it.


    arr[0] is an array 13 T. arr[1] is an array of 13 T. arr[2] does not
    exist. arr[j] is an object of type T as long as 0<=i<=1 and
    0<=j<=12. arr[j] is an element of arr but not element of arr.
    arr is an element of arr and it is an array.


    Remove del for email
     
    Barry Schwarz, May 9, 2008
    #5
  6. mdh

    mdh Guest

    On May 8, 8:54 pm, Barry Schwarz <> wrote:
    >
    >
    > The C99 standard uses the term "multidinensional array" so K&R is
    > slightly out of date in this regard.
    >
    > >Looking at the debugger I use, arr[2][13] is shown as an initial value
    > >of "2", but when expanded, there are 2 consecutive arrays of 13
    > >elements.

    >
    > What do you mean by "2".  Is it an array of char arrays and the first
    > of such holds the string '2' '\0'?



    I am using Xcode...not that that probably makes any difference.
    Initially arr[2][13] is declared as a char array. In the debugger
    window, there is a column for value and the "initial" value of arr is
    "2". If one expands this, then one sees 2 arrays of 13 elements, and
    as you say below, these seem to be contiguous. I was trying to find a
    way of seeing what the address of each element is, but have been
    unable to do so....


    >
    > It is true that the 26 "basic elements" of arr will appear in memory
    > "linearly".  This has prompted many debates about whether a pointer to
    > arr[0][0] can be used with subscripts ranging from 0 to 25 to access
    > all 26.  What is not in dispute is that in a 1d array T x[N], x[0]
    > evaluates to an element of type T.  In your case, arr[0] evaluates to
    > an array of T.  To my mind, this is sufficient to say arr cannot be
    > considered a 1d array.
    >



    thank you Barry.
     
    mdh, May 9, 2008
    #6
  7. mdh

    Default User Guest

    pete wrote:

    > Default User wrote:
    > > Joe Wright wrote:
    > >
    > > > mdh wrote:

    > >
    > > > Perfect sense. All above is correct. Given 'int arr[2][13];', arr
    > > > is an array 2 of array 13 of int. 26 consecutive ints.
    > > >
    > > > > The exercise associated with this, used the construct
    > > > >
    > > > > *p = arr[1 or 0 ] to point to either the "first" or "second"
    > > > > row of the array. Does the compiler "know" where to point to
    > > > > because it has been given this information by the declaration
    > > > > of "13" in arr[2][13]. Hopefully this makes sense too!
    > > > >
    > > > No. arr[0] is (the address of) an array 13 of int.

    > >
    > > No, it's not. It is an array 13 of int, not a pointer to one. arr
    > > is a pointer to array 13 of int.

    >
    > You just made the same mistake that you just corrected.


    Yes, I did in a way. I was sloppy about context. It is correct that arr
    is not a pointer, although it's converted to one in most contexts.

    The code was correct, which it wasn't originally.


    Thanks for clarifying my stab at i.





    Brian
     
    Default User, May 9, 2008
    #7
  8. mdh

    mdh Guest


    >
    >
    > >The exercise associated with this, used the construct

    >
    > > *p = arr[1 or 0 ] to point to either the "first" or "second" row of
    > >the array. Does the compiler "know" where to point to because it has
    > >been given this information by the declaration of "13" in arr[2][13].
    > >Hopefully this makes sense too!

    >
    > Yes and yes.
    >

    I was in a hurry to get to work this am...so forgot to ask this.
    In a multidimensional array, one can simply drop the second []? as in
    *p=arr and this is legal?
    Thanks.
     
    mdh, May 10, 2008
    #8
  9. pete <> writes:

    > mdh wrote:
    >>>
    >>>> The exercise associated with this, used the construct
    >>>> *p = arr[1 or 0 ] to point to either the "first" or "second" row of
    >>>> the array. Does the compiler "know" where to point to because it has
    >>>> been given this information by the declaration of "13" in arr[2][13].
    >>>> Hopefully this makes sense too!
    >>> Yes and yes.
    >>>

    >> I was in a hurry to get to work this am...so forgot to ask this.
    >> In a multidimensional array, one can simply drop the second []? as in
    >> *p=arr and this is legal?
    >> Thanks.

    >
    > It's legal regardless of whether or not
    > you understand what you're writing.
    > But it's better if you realize that
    >
    > *p = arr;
    >
    > means the same thing as
    >
    > *p = &arr[0];


    The trouble is this phrase "means the same as". Both right hand sides
    are certainly closely related expressions, but they have different
    types, different sizes (sizeof arr != sizeof &arr[0]) and they
    can't be used in the same places (you can, for example take the
    address of one but not of the other).

    Sometimes it helps to gloss over these differences and sometimes it
    does not. I am not sure which is the case here.

    > because
    >
    > &arr[0] means &*(*(arr + i) + 0)
    >
    > which can be simplified to
    >
    > (*(arr + i) + 0)
    > *(arr + i)
    > arr


    C is not good for equational reasoning. The OP might find this
    helpful:

    #include <stdio.h>

    #define PSZ(exp) printf("sizeof " #exp " = %d\n", (int)sizeof exp)

    int main(void)
    {
    int i = 0;
    int arr[2][13] = {0};

    PSZ(&arr[0]);
    PSZ(&*(*(arr + i) + 0));
    PSZ((*(arr + i) + 0));
    PSZ(*(arr + i));
    PSZ(arr);

    return 0;
    }

    --
    Ben.
     
    Ben Bacarisse, May 10, 2008
    #9
  10. pete <> writes:

    > Ben Bacarisse wrote:
    >> pete <> writes:

    <snip>
    >>> But it's better if you realize that
    >>>
    >>> *p = arr;
    >>>
    >>> means the same thing as
    >>>
    >>> *p = &arr[0];

    >>
    >> The trouble is this phrase "means the same as". Both right hand sides
    >> are certainly closely related expressions, but they have different
    >> types, different sizes (sizeof arr != sizeof &arr[0]) and they
    >> can't be used in the same places (you can, for example take the
    >> address of one but not of the other).

    >
    > Think harder.


    OK, but you'll have to help me if you think I've missed something. I
    really do think I get it.

    I know you meant "in most expression contexts" and I did not say you
    said anything wrong. All I was saying is that it sometimes helps to
    know the ways in which they *don't* mean the same thing. Obviously
    you disagree, and that is fine. Only the OP can say which is more
    helpful in "getting it".

    > *p = arr;
    > means the same thing as
    > *p = (arr + 0);
    >
    > sizeof arr
    > does not mean the same thing as
    > sizeof (arr + 0)


    Of course not, and that is one reason why I'd be loath to say that
    arr and &arr[0] mean the same thing.

    sizeof &arr[0]

    *does* mean the same thing as

    sizeof (&arr[0] + 0)

    (as do '*p = &arr[0];' and '*p = &arr[0] + 0;').

    All this does is to highlight that we expect different things from two
    expressions that "mean the same".

    --
    Ben.
     
    Ben Bacarisse, May 10, 2008
    #10
  11. Joe Wright <> writes:
    <snip>
    > All true on the face of it but sizeof was not what was asked, it was
    > assignment.


    Yes, I know I took it out of context. It was deliberate because I
    wanted to point out that context was critical. Maybe I complicated
    matters and, if so, I am sorry.

    --
    Ben.
     
    Ben Bacarisse, May 10, 2008
    #11
  12. pete <> writes:

    > Ben Bacarisse wrote:

    <snip>
    >> OK, but you'll have to help me if you think I've missed something. I
    >> really do think I get it.
    >>
    >> I know you meant "in most expression contexts"

    >
    > I didn't mean that.
    > I meant that given
    >
    > int arr[2][13], **p, i;
    >
    > then
    >
    > *p = arr;
    >
    > means exactly the same thing as
    >
    > *p = &arr[0];


    Gotcha. You were making a very narrow point.

    Sadly, you led me a little up the path I ended up running down.
    Rather than stopping there, you went on to expand &arr[0] in stages
    (without the *p = context) which I jumped on as implying a more
    general equivalence.

    If you'd kept the context and written:

    "*p = &arr[0] means *p = &*(*(arr + i) + 0)

    which can be simplified to

    *p = (*(arr + i) + 0)
    *p = *(arr + i)
    *p = arr

    I hope I'd have kept out of it.

    --
    Ben.
     
    Ben Bacarisse, May 11, 2008
    #12
  13. On May 9, 8:35 pm, mdh <> wrote:

    >  I was in a hurry to get to work this am...so forgot to ask this.
    > In a multidimensional array, one can simply drop the second []?  as in
    > *p=arr and this is legal?


    Depending on the type of p. If arr is defined as T arr[N][M], then
    for your code to be legal, p must be a T**. *p will then have type T*
    and arr will be converted to &arr[0] which is also of type T*.

    Far more common is for p to be a T* and the assignment to read
    p = arr.
     
    Barry Schwarz, May 11, 2008
    #13
  14. mdh

    mdh Guest

    On May 11, 4:17 am, Barry Schwarz <> wrote:
    > On May 9, 8:35 pm, mdh <> wrote:
    >
    >
    > Depending on the type of p.  If arr is defined as T arr[N][M], then
    > for your code to be legal, p must be a T**.  *p will then have type T*
    > and arr will be converted to &arr[0] which is also of type T*.
    >
    > Far more common is for p to be a T* and the assignment to read
    > p = arr.



    Well...I **think** I see it a little more clearly.
    Although once admonished for writing code to figure things out, a weak
    attempt follows.

    #include <stdio.h>

    int main (int argc, const char * argv[])
    {
    int i, j, k, l;
    char arr [3][3] = {"One", "Two", "Lst"};
    char *p;
    char **q;

    for ( i = 0; i < 3; i ++)
    for ( j= 0; j < 3; j++)
    {
    p=&arr[j];
    printf( "%p\n", p);
    }

    putchar('\n');

    for ( k = 0; k < 3; k ++)
    for ( l= 0; l < 3; l++)
    {
    p=arr[k];
    q=&arr[k][l];
    printf( "%s %s\n", p, q);
    }
    }
    output:

    0xbffff7cf
    0xbffff7d0
    0xbffff7d1
    0xbffff7d2
    0xbffff7d3
    0xbffff7d4
    0xbffff7d5
    0xbffff7d6
    0xbffff7d7

    OneTwoLst OneTwoLst
    OneTwoLst neTwoLst
    OneTwoLst eTwoLst
    TwoLst TwoLst
    TwoLst woLst
    TwoLst oLst
    Lst Lst
    Lst st
    Lst t

    Which I think says, as mentioned above, that the addresses are
    contiguous. So at least that is an easy visual and conceptual concept
    to comprehend.
    And to repeat what you put far more elegantly, more to see if I am
    understanding it,
    char *p in the context of the declaration arr[m][n], is a "row"
    and char **q, is a character?
     
    mdh, May 12, 2008
    #14
  15. mdh

    Default User Guest

    mdh wrote:


    > int main (int argc, const char * argv[])
    > {
    > int i, j, k, l;
    > char arr [3][3] = {"One", "Two", "Lst"};


    You do not reserve enough space for a null terminator. You will have
    arrays of char but not strings in your array.

    > char *p;
    > char **q;
    >
    > for ( i = 0; i < 3; i ++)
    > for ( j= 0; j < 3; j++)
    > {
    > p=&arr[j];
    > printf( "%p\n", p);


    You should cast p to void*.

    > }
    >
    > putchar('\n');
    >
    > for ( k = 0; k < 3; k ++)
    > for ( l= 0; l < 3; l++)
    > {
    > p=arr[k];
    > q=&arr[k][l];
    > printf( "%s %s\n", p, q);


    You attempt to pass the non-strings when printf() is expecting strings.
    Your program now exhibits undefined behavior. Nothing else about it
    will tell you very much.



    Brian
     
    Default User, May 12, 2008
    #15
  16. mdh

    mdh Guest

    On May 11, 8:16 pm, Richard Heathfield <> wrote:
    >
    > Writing code "to figure things out" is a two-edged sword. It can certainly
    > be helpful for discovering how things *appear* to work, but it is a poor
    > guide for discovering how things *must* work.



    Point made and taken...thanks.


    > > char arr [3][3] = {"One", "Two", "Lst"};

    >
    > Legal, but dangerous. Don't treat these arrays of char as if they were
    > strings. They aren't.


    OK..now let me show my total ignorance.

    So, can multidim char arrays ever be treated as strings and would
    this then be the correct intialization? char arr[] [] = "one, two";
    And, for a regular (one dim) char array, would this be a string
    intialization? char arr[]= "something" or the use of strcpy?

    And, somewhat philosophically, a (one dim) char array is simply a
    contiguous set of bytes. If one ? *knows* the array is NULL
    terminated, then we can safely treat it as a string. But the *only*
    way to know this is if it is correctly initialized in the first place.
    Is this a fair way of looking at it?



    > > p=&arr[j];
    > > printf( "%p\n", p);

    >
    > Although the representations of char * and void * are required to be the
    > same, it is generally wiser to insist on void * for %p:
    >
    > printf("%p\n", (void *)p);


    I did read today about the need for a pointer to be cast to
    void ...but is there a reason for this? Other than the language says
    it should be so.


    >
    > You fell into the trap.


    Yup!

    > The easiest way to comprehend multidimensional arrays is to think of them
    > as arrays of arrays. If you never try to breach the bounds of an object,
    > all will be well. By treating arrays-of-arrays as if they were a single
    > contiguous object (EVEN IF THAT IS TRUE), you're violating that principle


    Yes..I like it...thanks.
     
    mdh, May 13, 2008
    #16
  17. mdh

    mdh Guest


    >
    > You attempt to pass the non-strings when printf() is expecting strings.
    > Your program now exhibits undefined behavior. Nothing else about it
    > will tell you very much.
    >



    Thanks Brian...I think I am beginning to understand this.Not quite
    there yet...but getting closer!! Next onto function pointers!!!
     
    mdh, May 13, 2008
    #17
  18. mdh

    mdh Guest

    Thanks Richard, as usual, for your insights.
     
    mdh, May 13, 2008
    #18
  19. mdh

    Chris Torek Guest

    In article <>
    Richard Heathfield <> wrote:
    >... strcpy can never initialise anything, because initialisation is what
    >you do to an object at the point where it is created.


    In the sense of "an initializer" (as used in Standard C), yes.
    However, one should be aware that many (perhaps even most?) people
    also refer to the first assignment to something as its
    "initialization", and then use the word "initialize" (or
    "initialise") to describe what happens at that point.

    That is:

    void f(void) {
    int i = 0;
    int j;

    ... code that does not touch j ...
    j = 0;
    ...
    }

    In Standard C terminology, the variable i has an initializer and
    is initialized to 0. The variable j has no initializer and is not
    initialized. The assignment "j = 0" is an ordinary assignment and
    does not "initialize" j ... but in many/most people's terminology,
    the assignment to j, which is its initial (i.e., first) assignment,
    does "initialize" j.

    In short, one must be careful with terminology, as the multiple
    meanings of various words do confuse people. :)
    --
    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: gmail (figure it out) http://web.torek.net/torek/index.html
     
    Chris Torek, May 13, 2008
    #19
  20. On May 11, 7:07 pm, mdh <> wrote:
    >
    > int main (int argc, const char * argv[])
    >         {


    Did you throw the const in just to annoy people? Is that "signature"
    properly documented on your system? How many other systems do you
    think will support it?
     
    Barry Schwarz, May 17, 2008
    #20
    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. Alf P. Steinbach
    Replies:
    0
    Views:
    454
    Alf P. Steinbach
    Aug 18, 2003
  2. John Harrison
    Replies:
    4
    Views:
    6,956
    Default User
    Aug 19, 2003
  3. Icosahedron
    Replies:
    8
    Views:
    688
    Vivek
    Aug 21, 2003
  4. Venkat
    Replies:
    4
    Views:
    1,014
    Venkat
    Dec 5, 2003
  5. Kenneth Brody

    Two-dimensional array to array of arrays

    Kenneth Brody, Dec 21, 2006, in forum: C Programming
    Replies:
    2
    Views:
    521
    Simon Biber
    Dec 21, 2006
Loading...

Share This Page