Skip to content

Instantly share code, notes, and snippets.

@willeccles
Last active June 11, 2019 11:47
Show Gist options
  • Save willeccles/afce021697ae6ca33f2d3abbfa7318d8 to your computer and use it in GitHub Desktop.
Save willeccles/afce021697ae6ca33f2d3abbfa7318d8 to your computer and use it in GitHub Desktop.
Using pointers to make huge blobs of data less painful to work with.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
The problem:
Say you have an array of N*M items. This is essentially
a 2D array, kept contiguously in memory (for example,
you have 15 devices, and their data is given to you
in a huge blob of 10 bytes each). We will call this
data_raw. Now, you know that you can get device0's data
by getting the first 10 items, and device1's data by
using 0+i*10 as an index, but that's ugly.
Instead, we can simulate a 2D array by using a list of
pointers to the huge array. We will call this
data_nice. This does use extra memory, in this case:
DEV_COUNT * sizeof(uint8_t*)
However, if the memory is available, this can just make
life easier.
Rationale:
Sure, it would be more efficient (by a decent amount)
to not do this. However, I recently ran into a situation
where a huge amount of code was using a 2D array, which
I would have had to replace with a giant blob of data.
Refactoring this would take forever! Luckily, using this
solution, a small performance hit (in that case, a very
small hit) resulted in less work to make old code
compatible. It also makes the code more readable anyway.
*/
// Experiment values:
#define DEV_COUNT 15UL
#define DEV_BYTES 10UL
typedef unsigned char uint8_t; // byte type
// Our data:
uint8_t* data_raw;
// Convenience array:
uint8_t** data_nice;
int main(void) {
// simulate getting data from devices
data_raw = malloc(DEV_COUNT * DEV_BYTES * sizeof(uint8_t));
for (int i = 0; i < DEV_COUNT * DEV_BYTES; i++) {
data_raw[i] = i;
}
// but now we want to get data the nice way
data_nice = malloc(DEV_COUNT * sizeof(uint8_t*));
for (int i = 0; i < DEV_COUNT; i++) {
data_nice[i] = data_raw + (i * DEV_BYTES);
}
// now let's print the data for proof that it worked
puts(" Device | Data");
for (int i = 0; i < DEV_COUNT; i++) {
printf(" %6d | ", i + 1);
for (int j = 0; j < DEV_BYTES; j++) {
printf("%s%3d", (j?", ":" "),
data_nice[i][j]);
}
puts("");
}
// and of course, don't forget to clean up
free(data_nice);
free(data_raw);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment