Copying an array slice (Was: Re: Difficulties with passing multi-dimensional arrays)



On Fri, 17 Jun 2005 05:56:11 +0000, Dave Thompson wrote:

> Or in C99 or in GNU C as an extension use a VLA which does this for
> you. It's easiest to pass the bound(s) _first_:
> void set_slice (int fullwidth, int (*ary) [fullwidth] )
> /* or int ary [] [fullwidth] if you prefer, it's exactly equivalent */
> { ... access ary[0:3][0:3] ... }
> ... set_slice (8, bg) /* accesses bg[0:3][0:3] */
> /* or better use something like Me's MAT_WIDTH macro */
> set_slice (8, &bg[2]) /* accesses bg[2:5][0:3] */
> set_slice (8, (int(*)[8])&bg[2][2]) /* bg[2:5][2:5] */
> /* this last case is yucky and if at all frequent
> would be handled better by saving an offset pointer
> or by going through a flattened pointer as below */

Nice one, I haven't seen that before. It gave me an idea for a function
to extract an arbitrary-size slice from an arbitrary-size 2D array and I
coded it. Not being familiar with the standards as many here seem to be,
I'd like to know whether this code is standard C and how portable it is.
Also if anyone could suggest which of the alternatives would generally be
optimal / better practice where I've commented: /* OR i * W + j; */ that
would be great. The first would seem to involve less calculation but
perhaps compiler optimisations would remove that seeming benefit - I know
it's hard to generalise about this sort of thing.

This code compiles under gcc with no warnings with options -Wall -std=c99
-pedantic and gives the expected output:

main array: width 10, height 5
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
slice in main array at X=4; Y=3; width 3, height 2
34 35 36
44 45 46
extracting that slice from main array...
extracted slice:
34 35 36
44 45 46

Here's the code:

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

#define W 10
#define H 5
#define SL_W 3
#define SL_H 2
#define SL_X 4
#define SL_Y 3

void print_slice(int fullwidth, int (*ary)[fullwidth], int width, int height)
{
int i, j;

for (i = 0; i < height; i++) {
for (j = 0; j < width; j++)
printf("%3d ", ary[i][j]);
printf("\n");
}
}

int *make_slice(int fullwidth, int (*ary)[fullwidth], int width, int height)
{
int (*slicep)[height][width];
int i;
size_t row_sz = sizeof((*slicep)[0]);

if (! (slicep = malloc(sizeof(*slicep))) )
exit(EXIT_FAILURE);
for (i = 0; i < height; i++)
memcpy(&(*slicep)[i], &ary[i], row_sz);
return (int *)slicep;
}

int main(int argc, char **argv)
{
int a2d[H][W];
int (*slicep)[SL_H][SL_W];
int i, j, k=0;

/* set array values */
for (i = 0; i < H; i++) {
for (j = 0; j < W; j++)
a2d[i][j] = k++; /* OR i * W + j; */
}

printf("main array: width %d, height %d\n", W, H);
print_slice(W, a2d, W, H);

printf("slice in main array at X=%d; Y=%d; width %d, height %d\n",
SL_X, SL_Y, SL_W, SL_H);
print_slice(W, (int(*)[])&a2d[SL_Y][SL_X], SL_W, SL_H);

printf("extracting that slice from main array...\n");
slicep = (int (*)[SL_H][SL_W])make_slice(W,
(int(*)[])&a2d[SL_Y][SL_X], SL_W, SL_H);

printf("extracted slice:\n");
print_slice(SL_W, *slicep, SL_W, SL_H);

free(slicep);
return EXIT_SUCCESS;
}

.



Relevant Pages

  • Re: how to extract a line trough a volume
    ... I have a 3d array let's say ... Following your suggestion I've created a 3d line between two ... I need to extract the values along a straight ray path ... My first tought was to construct a slice along the two ...
    (comp.soft-sys.matlab)
  • Re: how to extract a line trough a volume
    ... I have a 3d array let's say ... Following your suggestion I've created a 3d line between two ... I need to extract the values along a straight ray path ... My first tought was to construct a slice along the two ...
    (comp.soft-sys.matlab)
  • Re: how to extract a line trough a volume
    ... I have a 3d array let's say ... Following your suggestion I've created a 3d line between two ... I need to extract the values along a straight ray path ... My first tought was to construct a slice along the two ...
    (comp.soft-sys.matlab)
  • Re: BIGLOO vs FORTRAN
    ... multidimensional array if you wanna slice lets say: ... various dimensions and orders. ... (vector->list erg) ...
    (comp.lang.scheme)
  • Re: unsigned type
    ... says that for a slice, "If the slice is not a null slice (a slice ... that all index must be valid before checking for a null array. ... work with modular index types because the 'First of the string is the ...   ...
    (comp.lang.ada)

Loading