Skip to content

Instantly share code, notes, and snippets.

@DBJDBJ
Last active September 17, 2022 21:47
Show Gist options
  • Save DBJDBJ/385fc0b2c14640c71dd7d1d792557ef7 to your computer and use it in GitHub Desktop.
Save DBJDBJ/385fc0b2c14640c71dd7d1d792557ef7 to your computer and use it in GitHub Desktop.
https://stackoverflow.com/a/73755385/10870835 -- do not pass structs by value or by pointer
/*
(c) 2022 by dbj@dbj.org CC BY SA 4.0
Godbolt: https://godbolt.org/z/ne579e85f
The point is here we do not use naked pointer to pass the structs arround
we use handles to the preallocated slabs of the same struct
thus we do not suffer the perenial modern C dilema: should we pass the
structs by value or as pointers to them.
We are free to decide how are we going to preallocate the mx_slab depending
on the runtime parameters. The code using it stays the same.
We do also save a LOT of execution time by not calling small and frequent
malloc/free on lot of instances of individual structs.
*/
#include <stdio.h>
#define FX(F, X) printf("\n%5d %s :" F, __LINE__, (#X), (X))
#define MX_ROWS 3
#define MX_COLS 3
typedef struct mx_ {
int data[MX_ROWS][MX_COLS];
} mx;
#define MX_VAL_FMT "%2d"
typedef const int MX_HANDLE;
#define SLAB_SIZE 3
// obviously you understand if mx_slab is allocated on the
// heap the data[][] in here will be also residing on the heap
// and vice versa
// 3 rows, 3 columns each row, times the number of the slab size
// SLAB_SIZE * {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}
// on the start
// allocate mx_slab on the stack
// use mx_slab to the full capacity, set it to some values
mx mx_slab[SLAB_SIZE] = {(mx){{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}},
(mx){{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}},
(mx){{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}}};
// no free slots to start with
int slab_free_slots[SLAB_SIZE] = { /* all are set to 0 */ };
// notice how we avoid decision on how to pass mx struct
// instead we simply pass the handle to it
static void mx_print(MX_HANDLE mxh_) {
// the mx 'pointer' in here is just the mem adress
mx * mxp_ = &(mx_slab[mxh_]) ;
// we can also take the address of the data block
// inside the mx instance, in order to simplify the
// code using the mx instance
// note: this construct is pointer to array
int (*datap_)[MX_ROWS][MX_COLS] = & mxp_->data ;
printf("\nmx:%d { ", mxh_);
for (int R = 0; R < MX_ROWS; R++) {
printf("{");
for (int C = 0; C < MX_COLS; C++)
printf(MX_VAL_FMT, (*datap_)[R][C]);
printf(" }");
}
printf(" }");
}
static void slab_print_used(const int slab_size_ ) {
for (int k = 0; k < slab_size_; k++)
// do not print mx that is "free"
if (!slab_free_slots[k]) mx_print(k);
}
int main(void) {
slab_print_used(SLAB_SIZE);
return 42;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment