This uses a similar pointer to what Eric used, but I've added an array descriptor struct that can be passed around easily.
That is, from main, how do you pass the array to subfunctions? Especially, if you have to have multiple arrays that have differing dimensions?
The syntax of (e.g.):
struct pix (*pixels)[width] = malloc(sizeof(*pixels) * height);
can be cumbersome.
It can be simplified with a small bit of macro trickery.
Here's some code that illustrates the benefits of a struct and the convenience of being able to do true 2D indexing:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint32_t u32;
#define sysfault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
// pixel control
typedef struct pix {
u8 red;
u8 green;
u8 blue;
} pix_t;
// pixel array control
typedef struct arr {
size_t arr_width;
size_t arr_height;
pix_t *arr_pixels;
} arr_t;
#define ARR2DPTR(_arr) \
pix_t (*_arr##ptr)[_arr->arr_width] = \
(__typeof__(_arr##ptr)) _arr->arr_pixels
arr_t *
arrnew(size_t width,size_t height)
{
arr_t *arr = malloc(sizeof(*arr));
arr->arr_width = width;
arr->arr_height = height;
arr->arr_pixels = malloc(sizeof(*arr->arr_pixels) * width * height);
return arr;
}
void
pixpack(pix_t *pix,u32 off)
{
pix->red = (off >> 16);
pix->green = (off >> 8);
pix->blue = (off >> 0);
}
u32
pixunpack(const pix_t *pix)
{
u32 off = 0;
off |= ((u32) pix->red) << 16;
off |= ((u32) pix->green) << 8;
off |= ((u32) pix->blue) << 0;
return off;
}
void
arrfill(arr_t *arr)
{
pix_t *arrptr = arr->arr_pixels;
u32 off = 0;
for (size_t y = 0; y < arr->arr_height; ++y) {
for (size_t x = 0; x < arr->arr_width; ++x, ++off)
pixpack(&arrptr[(y * arr->arr_width) + x],off);
}
}
void
chk2ptr(arr_t *arr)
{
ARR2DPTR(arr);
u32 offexp = 0;
u32 offact;
for (size_t y = 0; y < arr->arr_height; ++y) {
for (size_t x = 0; x < arr->arr_width; ++x, ++offexp) {
offact = pixunpack(&arrptr[y][x]);
if (offact != offexp)
sysfault("chk2ptr: y=%zu x=%zu offexp=%u offact=%u\n",
y,x,offexp,offact);
}
}
}
void
chk1ptr(arr_t *arr)
{
pix_t *arrptr = arr->arr_pixels;
u32 offexp = 0;
u32 offact;
for (size_t y = 0; y < arr->arr_height; ++y) {
for (size_t x = 0; x < arr->arr_width; ++x, ++offexp) {
offact = pixunpack(&arrptr[(y * arr->arr_width) + x]);
if (offact != offexp)
sysfault("chk1ptr: y=%zu x=%zu offexp=%u offact=%u\n",
y,x,offexp,offact);
}
}
}
int
main(void)
{
arr_t *arr = arrnew(20,10);
arrfill(arr);
chk1ptr(arr);
chk2ptr(arr);
return 0;
}
struct pix (*pixels)[800] = malloc(600 * sizeof *pixels)?struct pix (*pixels)[cols] = malloc(rows * sizeof *pixels);sizeof *pizels, which is the size of 800 structs, since in that commentpixelsis a pointer to arrays of 800 structs.