Is the name of a 2-dimensional array equal to address of [0][0] element?

Discussion in 'C Programming' started by Luke Wu, Jan 17, 2005.

  1. Luke Wu

    Luke Wu Guest

    Hello,

    I'm having some problems understanding 2 dimensional arrays. My
    problem relates to the following code:

    #include <stdio.h>

    #define M 3
    #define N 3

    void ZeroInitArray(int **array, int m, int n); /* prototype */


    int main(void)
    {
    int array[M][N];

    int i, j;

    for(i=0; i < M; i++)
    {
    for(j=0; j < N; j++)
    {
    array[j] = i * j;
    }
    }

    ZeroInitArray(array, M, N);

    return 0;

    }


    void ZeroInitArray(int **array, int m, int n)
    {
    int i, j;

    for(i=0; i < m; i++)
    {
    for(j=0; j < n; j++)
    {
    array[j] = 0;
    }
    }
    }


    ===END OF CODE===

    Error message: My compiler reports that I am passing in an incorrect
    pointer type.

    I've read the FAQ on this subject, but still no enlightenment.

    >From what I understand, an array's name is equivalent to a pointer to

    it's first element.

    for example:

    int x[5];

    x = &x[0]; /* {pointer to first element) */


    So what doesn't this apply to two dimensional arrays?

    int x[5][5];

    /* to me, this two dimensional array is in fact an array of arrays..
    where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
    x[0] would be equivalent to a pointer to the first element of it's
    array.. &x[0][0]. So x[3] would be equivalent to &x[3][0]. The larger
    array (that holds the subarrays) has the name x, and it would be
    equivalent to the address of it's first element &x[0][0]. If this
    address is sent properly to the receiving function I used, then there
    should be no problem. Why is this illegal? Any insights would be
    helpful */
     
    Luke Wu, Jan 17, 2005
    #1
    1. Advertising

  2. Luke Wu

    Chris Torek Guest

    In article <>
    Luke Wu <> wrote:
    >I'm having some problems understanding 2 dimensional arrays.


    See the comp.lang.c FAQ, section 6 (sounds like you did already),
    and/or <http://web.torek.net/torek/c/pa.html>.

    [snippage]

    >From what I understand, an array's name is equivalent to a pointer to
    >its first element.


    It gets *converted to* a pointer to the first element.

    >So what doesn't this apply to two dimensional arrays?


    The trick is that C does not *have* two-dimensional arrays...

    >int x[5][5];
    >
    >/* to me, this two dimensional array is in fact an array of arrays..
    >where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
    >x[0] would be equivalent to a pointer to the first element of it's
    >array..


    All good so far, but here is where you go wrong:

    >&x[0][0].


    A pointer to the first element of the array "x" is &x[0], not
    &x[0][0]. See <http://web.torek.net/torek/c/pa.html>, and note
    the "size of the circle" parts (in this case, compare the red and
    black circles). These are determined by the types: &x[0] has type
    "pointer to array 5 of int" or "int (*)[5]". This type is not
    compatible with "int **", because "int **" does not point to a
    5-int-wide circle; and indeed, trying to force it to fit (via a
    cast, for instance) will produce code that fails at runtime, on
    typical implementations.
    --
    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, Jan 17, 2005
    #2
    1. Advertising

  3. Luke Wu

    Luke Wu Guest

    So then is this assumption wrong?:

    sample[A][C][D]; /* assume we declared 4 dimensional matrix */

    sample[a][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?
    Thank you
     
    Luke Wu, Jan 17, 2005
    #3
  4. "Luke Wu" <> wrote in
    <>:

    >#define M 3
    >#define N 3
    >...
    >void ZeroInitArray(int **array, int m, int n); /* prototype */
    >...
    >int array[M][N];
    >...
    >ZeroInitArray(array, M, N);
    >...
    >Error message: My compiler reports that I am passing in an incorrect
    >pointer type.


    Yes: you are attempting to pass a pointer to array to a function expecting a
    pointer to pointer.

    >I've read the FAQ on this subject, but still no enlightenment.
    >
    >From what I understand, an array's name is equivalent to a pointer to
    >it's first element.


    No, an array's name refers to the array. In certain (most) situations, an
    array expression "decays" to a pointer to its first element. One situation
    where it doesn't is as an argument to the sizeof operator: 'sizeof array'
    yields the total size of the array, not the size of a pointer to its first
    element.

    >for example:
    >
    >int x[5];
    >
    >x = &x[0]; /* {pointer to first element) */
    >
    >So what doesn't this apply to two dimensional arrays?
    >
    >int x[5][5];


    It does. However, just as an array of N int decays to a pointer to int, an
    array of array of N int decays to a *pointer to array of N int*. There is no
    further decay to a pointer to pointer to int. (If there were, what on earth
    would it point at, remembering that the array contains ints, not pointers?)

    >/* to me, this two dimensional array is in fact an array of arrays..
    >where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
    >x[0] would be equivalent to a pointer to the first element of it's
    >array.. &x[0][0]. So x[3] would be equivalent to &x[3][0]. The larger
    >array (that holds the subarrays) has the name x, and it would be
    >equivalent to the address of it's first element &x[0][0]. If this
    >address is sent properly to the receiving function I used, then there
    >should be no problem. Why is this illegal? Any insights would be
    >helpful */


    You're nearly there. The key is that the decay from array to pointer only
    happens to the outermost array. I'd suggest reading and digesting the FAQ
    entries on this again; they explain it a lot better than I can. :)

    -- Mat.
     
    Mathew Hendry, Jan 17, 2005
    #4
  5. Luke Wu wrote:
    > So then is this assumption wrong?:
    >
    > sample[A][C][D]; /* assume we declared 4 dimensional matrix */
    >
    > sample[a][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?


    No.

    sample[a] == *(sample + a)
    sample[a] == *( sample[a] + b ) == *( *(sample + a) + b )
    ....

    --
    Peter
     
    Peter Nilsson, Jan 17, 2005
    #5
  6. Luke Wu

    Luke Wu Guest

    I understand now.

    I think my confusion started with the fact that I didn't realize that
    multidimensional arrays are in fact stored in continguous storage
    elements and that the second dimension was just a way to step over
    large chunks of this contiguous array. I was assuming that there was
    an intermediate array (with pointers that pointed to different arrays
    of the last dimension) - much like one would do with dynamically
    allocated arrays using MALLOC.

    My prof should have just pointed us to the FAQ associated with this
    newsgroup instead of the horrid textbooks out there (Learn C in 21
    seconds, etc. etc.).


    Peter Nilsson wrote:
    > Luke Wu wrote:
    > > So then is this assumption wrong?:
    > >
    > > sample[A][C][D]; /* assume we declared 4 dimensional matrix */
    > >
    > > sample[a][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?

    >
    > No.
    >
    > sample[a] == *(sample + a)
    > sample[a] == *( sample[a] + b ) == *( *(sample + a) + b )
    > ...
    >
    > --
    > Peter
     
    Luke Wu, Jan 18, 2005
    #6
  7. Luke Wu

    pete Guest

    Luke Wu wrote:
    >
    > I understand now.
    >
    > I think my confusion started with the fact that I didn't realize that
    > multidimensional arrays are in fact stored in continguous storage
    > elements and that the second dimension was just a way to step over
    > large chunks of this contiguous array. I was assuming that there was
    > an intermediate array (with pointers that pointed to different arrays
    > of the last dimension) - much like one would do with dynamically
    > allocated arrays using MALLOC.
    >
    > My prof should have just pointed us to the FAQ associated with this
    > newsgroup instead of the horrid textbooks out there (Learn C in 21
    > seconds, etc. etc.).


    There's an html C89 last draft at:
    http://dev.unicals.com/papers/c89-draft.html
    and an N869 at:
    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/

    I recommend starting by reading "definition of terms"
    and "use of the library" first.
    In C89 draft that would be:
    1.6 DEFINITIONS OF TERMS
    4. LIBRARY
    4.1 INTRODUCTION
    in N869:
    3. Terms and definitions
    7. Library
    7.1 Introduction

    After that, the descriptions of the functions in the
    standard library are pretty easy to read, as long as you
    remember to read the introduction to the header first.
    In other words, before reading N869
    7.21.2.1 The memcpy function
    you should first review
    7.21.1 String function conventions

    --
    pete
     
    pete, Jan 18, 2005
    #7
  8. On Mon, 17 Jan 2005 19:25:35 -0800, Luke Wu wrote:

    > I understand now.
    >
    > I think my confusion started with the fact that I didn't realize that
    > multidimensional arrays are in fact stored in continguous storage
    > elements and that the second dimension was just a way to step over
    > large chunks of this contiguous array. I was assuming that there was
    > an intermediate array (with pointers that pointed to different arrays
    > of the last dimension) - much like one would do with dynamically
    > allocated arrays using MALLOC.


    Both layouts can be achieved with or without using malloc(), for example


    int (*p)[5] = malloc(4 * sizeof *p);

    will (if malloc succeeds) create an object that we can access through p
    with the same layout as

    int a[4][5];

    e.g. p[3][1] accesses an equivalent element to a[3][1]. The magic is in
    the type, p here is a pointer to an array of 5 ints. p[3] selects a
    particular sub-array of 5 ints and p[3][1] selects an int from that
    subarray.

    Lawrence
     
    Lawrence Kirby, Jan 18, 2005
    #8
  9. Luke Wu

    Luke Wu Guest

    Lawrence Kirby wrote:
    > On Mon, 17 Jan 2005 19:25:35 -0800, Luke Wu wrote:
    >
    > > I understand now.
    > >
    > > I think my confusion started with the fact that I didn't realize

    that
    > > multidimensional arrays are in fact stored in continguous storage
    > > elements and that the second dimension was just a way to step over
    > > large chunks of this contiguous array. I was assuming that there

    was
    > > an intermediate array (with pointers that pointed to different

    arrays
    > > of the last dimension) - much like one would do with dynamically
    > > allocated arrays using MALLOC.

    >
    > Both layouts can be achieved with or without using malloc(), for

    example
    >
    >
    > int (*p)[5] = malloc(4 * sizeof *p);
    >
    > will (if malloc succeeds) create an object that we can access through

    p
    > with the same layout as
    >
    > int a[4][5];
    >
    > e.g. p[3][1] accesses an equivalent element to a[3][1]. The magic is

    in
    > the type, p here is a pointer to an array of 5 ints. p[3] selects a
    > particular sub-array of 5 ints and p[3][1] selects an int from that
    > subarray.
    >
    > Lawrence



    So as far as the C standard is concerned, are the following true for a
    multidimensional array? (i.e., int array[3][3]; )

    1. array[1][2] < array [2][0]
    1a. array[1][2] + 1 == array[2][0]
    2. array[0][3] == array [1][0]
    3. array[2] > array [1] > array [0]

    I've seen some sample programs where a multidimensional array is passed
    to a function, but inside the function the array is treated as a single
    dimensional array to step through the elements. Is this a fair
    treatment under the C standard?

    ===

    >From everyone's help, I'm coming to the realization that there are not

    real multidimensional arrays in C, but only 2 types of simulated arrays
    (1. contiguous elements, and 2. intermediate array with poitners to
    subarrays - where traditional declaration using int array[A] uses
    array type 1.)

    Thanks everyone
     
    Luke Wu, Jan 18, 2005
    #9
    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:
    450
    Alf P. Steinbach
    Aug 18, 2003
  2. John Harrison
    Replies:
    4
    Views:
    6,949
    Default User
    Aug 19, 2003
  3. Venkat
    Replies:
    4
    Views:
    1,007
    Venkat
    Dec 5, 2003
  4. candide
    Replies:
    65
    Views:
    1,442
  5. John Koleszar

    address of static array element as address constant

    John Koleszar, Jul 7, 2008, in forum: C Programming
    Replies:
    7
    Views:
    642
    John Koleszar
    Jul 15, 2008
Loading...

Share This Page