Skip to content

Instantly share code, notes, and snippets.

@rexim
Created February 27, 2024 07:36
Show Gist options
  • Save rexim/b5b0c38f53157037923e7cdd77ce685d to your computer and use it in GitHub Desktop.
Save rexim/b5b0c38f53157037923e7cdd77ce685d to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#define da_append(xs, x) \
do { \
if ((xs)->count >= (xs)->capacity) { \
if ((xs)->capacity == 0) (xs)->capacity = 256; \
else (xs)->capacity *= 2; \
(xs)->items = realloc((xs)->items, (xs)->capacity*sizeof(*(xs)->items)); \
} \
\
(xs)->items[(xs)->count++] = (x); \
} while (0)
typedef struct {
int *items;
size_t count;
size_t capacity;
} Numbers;
int main(void)
{
Numbers xs = {0};
for (int x = 0; x < 10; ++x) da_append(&xs, x);
for (size_t i = 0; i < xs.count; ++i) printf("%d\n", xs.items[i]);
return 0;
}
@DanGdl
Copy link

DanGdl commented Feb 27, 2024

you can make your array with "generic type":
#define DA_ARRAY( name, dtype)
typedef struct {
dtype* items;
size_t count;
size_t capacity;
} name##Array##_t; \

@firephil
Copy link

firephil commented Feb 28, 2024

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    int *items;
    int count;
    int capacity;
} Numbers;

void resize(Numbers *xs, int new_capacity) {
    if (new_capacity < xs->count) {
        xs->count = new_capacity;
    }
    xs->items = realloc(xs->items, new_capacity * sizeof(*xs->items));
    xs->capacity = new_capacity;
}

void append(Numbers *xs, int x) {
    if (xs->count >= xs->capacity) {
        if (xs->capacity == 0) {
            xs->capacity = 64;
        } else {
            xs->capacity *= 2;
        }
        resize(xs, xs->capacity);
    }

    xs->items[xs->count++] = x;
}

int get(Numbers *xs, int index) {
  return xs->items[index];
}

int size(Numbers *xs) {
  return xs->count;
  }

int main(void) {
  Numbers xs;

  for (int i = 0; i < 10; ++i){
    append(&xs, i);
  }

  for (int i = 0; i < size(&xs); ++i){
    printf("%d\n", get(&xs, i));
  }
  return 0;
}```

@alternativepath
Copy link

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    int *items;
    int count;
    int capacity;
} Numbers;

void resize(Numbers *xs, int new_capacity) {
    if (new_capacity < xs->count) {
        xs->count = new_capacity;
    }
    xs->items = realloc(xs->items, new_capacity * sizeof(*xs->items));
    xs->capacity = new_capacity;
}

void append(Numbers *xs, int x) {
    if (xs->count >= xs->capacity) {
        if (xs->capacity == 0) {
            xs->capacity = 64;
        } else {
            xs->capacity *= 2;
        }
        resize(xs, xs->capacity);
    }

    xs->items[xs->count++] = x;
}

int get(Numbers *xs, int index) {
  return xs->items[index];
}

int size(Numbers *xs) {
  return xs->count;
  }

int main(void) {
  Numbers xs;

  for (int i = 0; i < 10; ++i){
    append(&xs, i);
  }

  for (int i = 0; i < size(&xs); ++i){
    printf("%d\n", get(&xs, i));
  }
  return 0;
}```

Nice!
However re-assigning a pointer directly from realloc is potentially a memory leak and many tools will yell at you.('xs->items' may be set to null if 'realloc' fails, which may result in a leak of the original buffer from clang-tidy)
I know this is a tangent but its just a good to know.

void resize(Numbers* xs, int new_capacity) {
    if (new_capacity < xs->count) {
        xs->count = new_capacity;
    }

    int* new_items = realloc(xs->items, new_capacity * sizeof(*xs->items));
    if (new_items == NULL) {
        perror("realloc");
        free(xs->items);
        exit(1); // handle re-allocation failure
    }

    xs->items = new_items;
    xs->capacity = new_capacity;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment