4 ms·
I think this is an interesting change, even though I (as someone who has loved C for 30+ years and use it daily in a professional capacity) don't immediately se
by unwind 1y ago
I think this is an interesting change, even though I (as someone who has loved C for 30+ years and use it daily in a professional capacity) don't immediately see a lot of use-cases I'm sure they can be found as the author demonstrates. Cool, and a good post!
- deleted 1y ago[deleted]
- glouwbug 1y agoCombined with C23's auto (see vec_for) you can technically backport the entirety of C++'s STL (of course with skeeto's limitation in his last paragraph in mind). gcc -std=c23. It is a _very_ useful feature for even the mundane, like resizable arrays: #include <stdlib.h> #include <stdio.h> #define vec(T) struct { T* val; int size; int cap; } #define vec_push(self, x) { \ if((self).size == (self).cap) { \ (self).cap = (self).cap == 0 ? 1 : 2 * (self).cap; \ (self).val = realloc((self).val, sizeof(*(self).val) * (self).cap); \ } \ (self).val[(self).size++] = x; \ } #define vec_for(self, at, ...) \ for(int i = 0; i < (self).size; i++) { \ auto at = &(self).val[i]; \ __VA_ARGS__ \ } typedef vec(char) string; void string_push(string* self, char* chars) { if(self->size > 0) { self->size -= 1; } while(*chars) { vec_push(*self, *chars++); } vec_push(*self, '\0'); } int main() { vec(int) a = {}; vec_push(a, 1); vec_push(a, 2); vec_push(a, 3); vec_for(a, at, { printf("%d\n", *at); }); vec(double) b = {}; vec_push(b, 1.0); vec_push(b, 2.0); vec_push(b, 3.0); vec_for(b, at, { printf("%f\n", *at); }); string c = {}; string_push(&c, "this is a test"); string_push(&c, " "); string_push(&c, "for c23"); printf("%s\n", c.val); }
- int_19h 1y agoWhat I don't quite get is why they didn't go all the way in and basically enabled full fledged structural typing for anonymous structs.
- uecker 1y agoThat way my plan, but the committee had concerns about type safety.
- int_19h 1y agoThis would probably need some special rules around stuff like: typedef struct { ... } foo_t; typedef struct { ... } bar_t; foo_t foo = (bar_t){ ... }; i.e. these are meant to be named types and thus should remain nominal even though it's technically a typedef. And ditto for similarly defined pointer types etc. But this is a pattern regular enough that it can just be special-cased while still allowing proper structural typing for cases where that's obviously what is intended (i.e. basically everywhere else).
- uecker 1y agoI agree, that is also the solution I suggested. I will try to bring this back for C2y.