Last active
September 17, 2022 21:47
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
(c) 2022 by [email protected] 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