Map 2D array to contiguous memory?

Discussion in 'C Programming' started by boltar2003@boltar.world, Jul 16, 2012.

  1. Guest

    This is probably a question thats come up before but google doesn't seem to
    be my friend on this one.

    Is there some hack whereby a 2D array can be mapped onto a dynamically
    allocated block of contiguous memory in C? Its easily done with 1D arrays
    but if you use a double pointer for the 2D the memory can't be contiguous
    as you have to allocate each single point in turn.

    What I'd like to do is something like:

    struct mystruct **array;

    array = (struct mystruct **)<some preallocated shared memory>
    :
    :
    array[1][2].val = 123;

    Now I know this will crash as soon as it tries to dereference the 1st
    level of the array but is there some clever way to do it?

    Thanks for any help.

    B2003
     
    , Jul 16, 2012
    #1
    1. Advertising

  2. writes:

    > This is probably a question thats come up before but google doesn't seem to
    > be my friend on this one.


    The C FAQ is useful here though I don't think it answers this exact
    question. http://c-faq.com/

    > Is there some hack whereby a 2D array can be mapped onto a dynamically
    > allocated block of contiguous memory in C? Its easily done with 1D arrays
    > but if you use a double pointer for the 2D the memory can't be contiguous
    > as you have to allocate each single point in turn.
    >
    > What I'd like to do is something like:
    >
    > struct mystruct **array;
    >
    > array = (struct mystruct **)<some preallocated shared memory>
    > :
    > :
    > array[1][2].val = 123;
    >
    > Now I know this will crash as soon as it tries to dereference the 1st
    > level of the array but is there some clever way to do it?


    You can make the memory contiguous[1] (at the expense of some alignment
    issues) but I want to ask why you need to do this. Why are you trying a
    hand behind your back?

    I am not saying that there aren't reasons to prefer this data
    arrangement over another, but it often proves to be a waste of time to
    explain just one of these when it later turns out that another, simpler,
    arrangement meets the requirements just as well. In sort, what is it
    that you are doing?

    [1] So you don't think I'm just withholding for the sake of it, here's
    how. Allocate space for array of pointer and for the array itself in
    one blob. You might need some padding between them to ensure that that
    structs are properly aligned. You then need to fix up the pointers to
    point into this blob.

    --
    Ben.
     
    Ben Bacarisse, Jul 16, 2012
    #2
    1. Advertising

  3. Guest

    On Mon, 16 Jul 2012 12:34:28 +0100
    Ben Bacarisse <> wrote:
    >You can make the memory contiguous[1] (at the expense of some alignment
    >issues) but I want to ask why you need to do this. Why are you trying a
    >hand behind your back?


    I'm not. I want 2 programs to share multidimentional data via shared
    memory which as you might be aware consists of contiguous blocks of
    memory. I'm simply wondering if there's a way to do this using the standard
    C array syntax.

    >[1] So you don't think I'm just withholding for the sake of it, here's
    >how. Allocate space for array of pointer and for the array itself in
    >one blob. You might need some padding between them to ensure that that
    >structs are properly aligned. You then need to fix up the pointers to
    >point into this blob.


    There must be an easier way than that.

    B2003
     
    , Jul 16, 2012
    #3
  4. writes:

    > This is probably a question thats come up before but google doesn't seem to
    > be my friend on this one.
    >
    > Is there some hack whereby a 2D array can be mapped onto a dynamically
    > allocated block of contiguous memory in C? Its easily done with 1D arrays
    > but if you use a double pointer for the 2D the memory can't be contiguous
    > as you have to allocate each single point in turn.


    You can map the 2D array onto a 1D array. Instead of allocating
    Arr2[xmax][ymax], instead allocate Arr1[xmax*ymax], and access it
    as Arr1[xmax*y + x].

    --
    /Wegge

    Leder efter redundant peering af dk.*,linux.debian.*
     
    Anders Wegge Keller, Jul 16, 2012
    #4
  5. Eric Sosman Guest

    On 7/16/2012 5:23 AM, wrote:
    > This is probably a question thats come up before but google doesn't seem to
    > be my friend on this one.
    >
    > Is there some hack whereby a 2D array can be mapped onto a dynamically
    > allocated block of contiguous memory in C? Its easily done with 1D arrays
    > but if you use a double pointer for the 2D the memory can't be contiguous
    > as you have to allocate each single point in turn.
    >
    > What I'd like to do is something like:
    >
    > struct mystruct **array;
    >
    > array = (struct mystruct **)<some preallocated shared memory>
    > :
    > :
    > array[1][2].val = 123;
    >
    > Now I know this will crash as soon as it tries to dereference the 1st
    > level of the array but is there some clever way to do it?


    struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    #define array (*arrayptr)
    array[9][17].member= 123;

    --
    Eric Sosman
    d
     
    Eric Sosman, Jul 16, 2012
    #5
  6. On 2012-07-16, Eric Sosman <> wrote:
    > On 7/16/2012 5:23 AM, wrote:
    >> What I'd like to do is something like:
    >>
    >> struct mystruct **array;
    >>
    >> array = (struct mystruct **)<some preallocated shared memory>
    >> :
    >> :
    >> array[1][2].val = 123;
    >>
    >> Now I know this will crash as soon as it tries to dereference the 1st
    >> level of the array but is there some clever way to do it?

    >
    > struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    > #define array (*arrayptr)
    > array[9][17].member= 123;


    Is there a particular reason why not simply

    struct mystruct (*thing)[99] = (void*)&whatever;
    thing[9][17].member = 123;

    instead of the above? (Especially the #define looks really suspicious.)

    --
    Heikki Kallasjoki
     
    Heikki Kallasjoki, Jul 16, 2012
    #6
  7. Guest

    On Mon, 16 Jul 2012 08:38:14 -0400
    Eric Sosman <> wrote:
    >On 7/16/2012 5:23 AM, wrote:
    >> This is probably a question thats come up before but google doesn't seem to
    >> be my friend on this one.
    >>
    >> Is there some hack whereby a 2D array can be mapped onto a dynamically
    >> allocated block of contiguous memory in C? Its easily done with 1D arrays
    >> but if you use a double pointer for the 2D the memory can't be contiguous
    >> as you have to allocate each single point in turn.
    >>
    >> What I'd like to do is something like:
    >>
    >> struct mystruct **array;
    >>
    >> array = (struct mystruct **)<some preallocated shared memory>
    >> :
    >> :
    >> array[1][2].val = 123;
    >>
    >> Now I know this will crash as soon as it tries to dereference the 1st
    >> level of the array but is there some clever way to do it?

    >
    > struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    > #define array (*arrayptr)
    > array[9][17].member= 123;


    Excellent , just what I was looking for - thank you. There's always a simple
    way eventually thats obvious when you see it :eek:)

    B2003
     
    , Jul 16, 2012
    #7
  8. Eric Sosman Guest

    On 7/16/2012 8:49 AM, Heikki Kallasjoki wrote:
    > On 2012-07-16, Eric Sosman <> wrote:
    >> On 7/16/2012 5:23 AM, wrote:
    >>> What I'd like to do is something like:
    >>>
    >>> struct mystruct **array;
    >>>
    >>> array = (struct mystruct **)<some preallocated shared memory>
    >>> :
    >>> :
    >>> array[1][2].val = 123;
    >>>
    >>> Now I know this will crash as soon as it tries to dereference the 1st
    >>> level of the array but is there some clever way to do it?

    >>
    >> struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    >> #define array (*arrayptr)
    >> array[9][17].member= 123;

    >
    > Is there a particular reason why not simply
    >
    > struct mystruct (*thing)[99] = (void*)&whatever;
    > thing[9][17].member = 123;
    >
    > instead of the above? (Especially the #define looks really suspicious.)


    <facepalm> Yes, that would work. </facepalm>

    <lame_excuse> With mine, `sizeof array' works better. </lame_excuse>

    --
    Eric Sosman
    d
     
    Eric Sosman, Jul 16, 2012
    #8
  9. Guest

    On Mon, 16 Jul 2012 12:49:42 GMT
    Heikki Kallasjoki <> wrote:
    >On 2012-07-16, Eric Sosman <> wrote:
    >> On 7/16/2012 5:23 AM, wrote:
    >>> What I'd like to do is something like:
    >>>
    >>> struct mystruct **array;
    >>>
    >>> array = (struct mystruct **)<some preallocated shared memory>
    >>> :
    >>> :
    >>> array[1][2].val = 123;
    >>>
    >>> Now I know this will crash as soon as it tries to dereference the 1st
    >>> level of the array but is there some clever way to do it?

    >>
    >> struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    >> #define array (*arrayptr)
    >> array[9][17].member= 123;

    >
    >Is there a particular reason why not simply
    >
    > struct mystruct (*thing)[99] = (void*)&whatever;
    > thing[9][17].member = 123;
    >
    >instead of the above? (Especially the #define looks really suspicious.)


    It'll compile but it won't work properly because it doesn't know how big
    the second dimension of the array is.

    B2003
     
    , Jul 16, 2012
    #9
  10. On 2012-07-16, <> wrote:
    > On Mon, 16 Jul 2012 12:49:42 GMT
    > Heikki Kallasjoki <> wrote:
    >>On 2012-07-16, Eric Sosman <> wrote:
    >>> On 7/16/2012 5:23 AM, wrote:
    >>>> What I'd like to do is something like:
    >>>>
    >>>> struct mystruct **array;
    >>>>
    >>>> array = (struct mystruct **)<some preallocated shared memory>
    >>>> :
    >>>> :
    >>>> array[1][2].val = 123;
    >>>>
    >>>> Now I know this will crash as soon as it tries to dereference the 1st
    >>>> level of the array but is there some clever way to do it?
    >>>
    >>> struct mystruct (*arrayptr)[18][99] = (void*)&whatever;
    >>> #define array (*arrayptr)
    >>> array[9][17].member= 123;

    >>
    >>Is there a particular reason why not simply
    >>
    >> struct mystruct (*thing)[99] = (void*)&whatever;
    >> thing[9][17].member = 123;
    >>
    >>instead of the above? (Especially the #define looks really suspicious.)

    >
    > It'll compile but it won't work properly because it doesn't know how big
    > the second dimension of the array is.


    It will certainly work properly, if you use it properly:

    struct mystruct (*p)[42] = malloc(33 * sizeof *p);
    p[32][41].member = 123; /* furthest corner of the 33-times-42 array */

    The above is completely analoguous to the one-dimensional case (except
    that the elements above are 42-element arrays of struct mystruct,
    whereas here they are single struct mystructs):

    struct mystruct *p = malloc(33 * sizeof *p);
    p[32].member = 123; /* last element of the 33-element array */

    (As mentioned, the version using a pointer to a 33-times-42-sized array,
    a struct mystruct (*p)[33][42], does have the advantage that sizeof *p
    will yield the size of the entire array, possibly simplifying the
    allocation.)

    --
    Heikki Kallasjoki
     
    Heikki Kallasjoki, Jul 16, 2012
    #10
  11. Guest

    On Mon, 16 Jul 2012 13:31:50 GMT
    Heikki Kallasjoki <> wrote:
    >> It'll compile but it won't work properly because it doesn't know how big
    >> the second dimension of the array is.

    >
    >It will certainly work properly, if you use it properly:
    >
    > struct mystruct (*p)[42] = malloc(33 * sizeof *p);
    > p[32][41].member = 123; /* furthest corner of the 33-times-42 array */


    Sure, it'll set it ok , but then something else will come and stomp on it
    later. Try this:

    struct st_point
    {
    double x;
    double y;
    };

    struct st_point (*grid)[10];

    int main()
    {
    int x;
    int y;

    grid = malloc(sizeof(struct st_point) * 50);

    for(x=0;x < 5;++x)
    {
    for(y=0;y < 10;++y)
    {
    grid[x][y].x = x;
    grid[x][y].y = y;
    }
    }
    printf("%f,%f %f,%f\n",
    grid[6][1].x,grid[6][1].y,grid[7][3].x,grid[7][3].y);
    return 0;
    }


    B2003
     
    , Jul 16, 2012
    #11
  12. Guest

    On Mon, 16 Jul 2012 13:37:48 +0000 (UTC)
    wrote:
    > printf("%f,%f %f,%f\n",
    > grid[6][1].x,grid[6][1].y,grid[7][3].x,grid[7][3].y);
    > return 0;


    Ignore me , got my indices the wrong way around. Amateur error.

    B2003
     
    , Jul 16, 2012
    #12
  13. Ike Naar Guest

    On 2012-07-16, <> wrote:
    > This is probably a question thats come up before but google doesn't seem to
    > be my friend on this one.
    >
    > Is there some hack whereby a 2D array can be mapped onto a dynamically
    > allocated block of contiguous memory in C? Its easily done with 1D arrays
    > but if you use a double pointer for the 2D the memory can't be contiguous
    > as you have to allocate each single point in turn.
    >
    > What I'd like to do is something like:
    >
    > struct mystruct **array;
    >
    > array = (struct mystruct **)<some preallocated shared memory>


    It's a FAQ, see

    http://c-faq.com/aryptr/dynmuldimary.html

    I think it's the "array2" example.
     
    Ike Naar, Jul 16, 2012
    #13
  14. writes:

    > On Mon, 16 Jul 2012 12:34:28 +0100
    > Ben Bacarisse <> wrote:
    >>You can make the memory contiguous[1] (at the expense of some alignment
    >>issues) but I want to ask why you need to do this. Why are you trying a
    >>hand behind your back?

    >
    > I'm not. I want 2 programs to share multidimentional data via shared
    > memory which as you might be aware consists of contiguous blocks of
    > memory. I'm simply wondering if there's a way to do this using the standard
    > C array syntax.


    The "tied hand" was your stipulation that you want a "double pointer"
    kind of 2D array.

    >>[1] So you don't think I'm just withholding for the sake of it, here's
    >>how. Allocate space for array of pointer and for the array itself in
    >>one blob. You might need some padding between them to ensure that that
    >>structs are properly aligned. You then need to fix up the pointers to
    >>point into this blob.

    >
    > There must be an easier way than that.


    I don't know of one.

    It turns out that you are happy to untie that hand because you don't really
    need the "double pointer" form.

    By the way, the answers you liked can all be made to use run-time array
    sizes if your compiler supports C99's "variably modified arrays".

    --
    Ben.
     
    Ben Bacarisse, Jul 16, 2012
    #14
  15. בת×ריך ×™×•× ×©× ×™,16 ביולי 2012 10:23:58 UTC+1, מ×ת (×œ× ×™×“×•×¢):
    >
    > Is there some hack whereby a 2D array can be mapped onto a dynamically
    > allocated block of contiguous memory in C?
    >

    One of the faults of C is that, in C89 at least, there's no way to do this

    void makeimage(int width, int height)
    {
    unsigned char image[height][width];
    }

    what you've got to do is allocate a 1d array on the heap and then access the pixel using the formula

    image[y*width+x] = pixelvalue;
    --
    Visti my website
    http://www.malcolmmclean.site11.com/www
     
    Malcolm McLean, Jul 18, 2012
    #15
  16. Tim Rentsch Guest

    Malcolm McLean <> writes:

    > [someone else wrote:]
    >>
    >> Is there some hack whereby a 2D array can be mapped onto a dynamically
    >> allocated block of contiguous memory in C?
    >>

    > One of the faults of C is that, in C89 at least, there's no way to do this
    >
    > void makeimage(int width, int height)
    > {
    > unsigned char image[height][width];
    > }
    >
    > what you've got to do is allocate a 1d array on the heap and then access the pixel using the formula
    >
    > image[y*width+x] = pixelvalue;


    You've misunderstood the point of the question. He's not asking
    about VLA's; he's asking about accessing dynamically allocated
    memory as though it's a 2D array. Even if he is using C90 (which
    he may be) and also needs dynamic rather than constant bounds
    (which appears not to be the case, but you never know), it still
    is possible to access dynically allocated contiguous memory as
    a 2D array, ie, using something like 'foo[j]'. But based on
    his comments it looks like all he needs are constant array bounds,
    not dynamic ones.
     
    Tim Rentsch, Jul 21, 2012
    #16
    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. panbru

    Contiguous memory blocks

    panbru, Aug 5, 2003, in forum: Python
    Replies:
    0
    Views:
    364
    panbru
    Aug 5, 2003
  2. Olumide
    Replies:
    9
    Views:
    2,005
    Dan Pop
    Nov 30, 2004
  3. Gary Kuehn
    Replies:
    2
    Views:
    483
    Gary Kuehn
    Jul 19, 2005
  4. Phil Endecott
    Replies:
    9
    Views:
    484
    Abhishek Padmanabh
    Feb 21, 2008
  5. chachi
    Replies:
    2
    Views:
    422
    Aaron Brady
    Nov 14, 2008
Loading...

Share This Page