Copying an array slice (Was: Re: Difficulties with passing multi-dimensional arrays)
- From: Netocrat <netocrat@xxxxxxxxxxx>
- Date: Mon, 20 Jun 2005 04:52:30 +1000
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;
}
.
- Follow-Ups:
- References:
- Difficulties with passing multi-dimensional arrays
- From: truckaxle
- Re: Difficulties with passing multi-dimensional arrays
- From: clayne
- Re: Difficulties with passing multi-dimensional arrays
- From: Dave Thompson
- Difficulties with passing multi-dimensional arrays
- Prev by Date: Re: void *malloc(size_t num_bytes);
- Next by Date: Re: simple question regarding 5.5 of Ritchie & Kernighan
- Previous by thread: Re: Difficulties with passing multi-dimensional arrays
- Next by thread: Re: Copying an array slice (Was: Re: Difficulties with passing multi-dimensional arrays)
- Index(es):
Relevant Pages
|
Loading