Live data from Hacker News

Generic Containers in C: Vec

uecker.codeberg.page

11–20 of 91 posts

Re: Generic Containers in C: Vec

#11

I doubt I'd want to use a dynamic array in C without a custom allocator.

You don't need an explicit allocator: you can create an empty object and vec_push() does the magic of (re)allocating the memory when needed.

Instead, what is missing is an automatic deallocator, one that's automatically called when the variable goes out of scope. For example:

  {
    vec(int) v={}; /* no extra room allocated */
    vec_push(v,1); /* space allocated */
    ... use v ...
  } /* here the space is dellocated, then v is released */
This example doesn't use the same definition of vec as TFA, but something more similar to 'span' by the same author.

Re: Generic Containers in C: Vec

#12
> Many vector types include a capacity field, so that resizing on every push can be avoided. I do not include one, because simplicity is more important to me and realloc often does this already internally. In most scenarios, the performance is already good enough.

I think this is the wrong decision (for a generic array library).

Re: Generic Containers in C: Vec

#13
post #12

> Many vector types include a capacity field, so that resizing on every push can be avoided. I do not include one, because simplicity is more important to me and realloc often does this already internally. In most scenarios, the performance is already good enough. I think this is the wrong decision (for a generic array library).

> realloc often does this already internally

Is Martin claiming that realloc is "often" maintaining a O(1) growable array for us?

That's what the analogous types in C++ or Rust, or indeed Java, Go, C# etc. provide.

Re: Generic Containers in C: Vec

#14

I think the overwhelmingly better approach for C is codegen here. Better ergonomics, tab completion, less error prone, etc. As long as your codegen is solid!

Why? I do not find the ergonomics bad.

It is also not clear how you get tap completion with code generation. But you could also get tab completion here, somebody just has to add this to the tab completion logic.

Re: Generic Containers in C: Vec

#15

I doubt I'd want to use a dynamic array in C without a custom allocator.

You don't need an explicit allocator: you can create an empty object and vec_push() does the magic of (re)allocating the memory when needed. Instead, what is missing is an automatic deallocator, one that's automatically called when the variable goes out of scope. For example: { vec(int) v={}; /* no extra room allocated */ vec_push(v,1); /* space allocated */ ... use v ... } /* here the space is dellocated, then v is…

And you could easily add a version with a custom allocator if you need it.

Re: Generic Containers in C: Vec

#16
The post is more of a quick-n-dirty (and rather trivial) proof of concept as the code includes only sporadical checks for allocation errors and then adds a hand-wavy disclaimer to improve it as needed.

E.g. in production code this

  if (!vec_ptr) // memory out
    abort();

  for (int i = 0; i 
should really be

  if (!vec_ptr) // memory out
    abort();

  for (int i = 0; i 
but it doesn't really roll of the tongue.

Re: Generic Containers in C: Vec

#17
post #12

> Many vector types include a capacity field, so that resizing on every push can be avoided. I do not include one, because simplicity is more important to me and realloc often does this already internally. In most scenarios, the performance is already good enough. I think this is the wrong decision (for a generic array library).

> realloc often does this already internally Is Martin claiming that realloc is "often" maintaining a O(1) growable array for us? That's what the analogous types in C++ or Rust, or indeed Java, Go, C# etc. provide.

No, I claim that the performance of realloc is good enough for most use cases because it also does not move the memory in case there is already enough space left.

I then mention that for other use cases, you can maintain a capacity field only in the part of the code where you need this.

Whether this is the right design for everybody, I do not know, but so far it is what I prefer for myself.

Re: Generic Containers in C: Vec

#18
post #16

The post is more of a quick-n-dirty (and rather trivial) proof of concept as the code includes only sporadical checks for allocation errors and then adds a hand-wavy disclaimer to improve it as needed. E.g. in production code this if (!vec_ptr) // memory out abort(); for (int i = 0; i should really be if (!vec_ptr) // memory out abort(); for (int i = 0; i but it doesn't really roll of the tongue.

If all you do is call abort anyway, you do not need an interface that makes you test for errors.

Re: Generic Containers in C: Vec

#20
It's amazing how many people try to write generic containers for C, when there is already a perfect solution for that, called C++. It's impossible to write generic type-safe code in C, and this version resorts to using GCC extensions to the language (note the ({…}) expressions).

For those afraid of C++: you don't have to use all of it at once, and compilers have been great for the last few decades. You can easily port C code to C++ (often you don't have to do anything at all). Just try it out and reassess the objections you have.

Post reply on HN