Earlier quoted context omitted.
You could take away anything you use and say "but we could make it ourselves", that doesn't mean it's helpful.
Except it’s very common for C programs to contain one-off data structures, so it’s not a hypothetical. It’s a concrete programming style.
I write type-safe generic data structures in C
121–130 of 196 posts
Re: I write type-safe generic data structures in C
#122For your level 2 code, `uint64_t data[];` is wrong for types whose alignment is greater than `uint64_t`, and also wasteful for types whose alignment is smaller (for example, under an ilp32 ABI on 64-bit architectures). For your level 3 code, it should be `int main() { List(Foo) foo_list = {NULL};` Note that working around a lack of `typeof` means you can't return anything. Also, your particular workaround allows `con…
I would love for `union`s to be federated, that is, a type could declare itself as thought it was part of a union with another type, without having to pre-declare all possible types in one place.
struct foo { ... };
struct bar { ... };
struct bar check_this_out(struct foo foo) {
return ((union { struct foo foo; struct bar bar; }){ .foo = foo}).bar;
}
struct bar *also_this(struct foo *foo) {
union { struct foo foo; struct bar bar; } *tmp = (void*)foo;
return &tmp->bar;
}Re: I write type-safe generic data structures in C
#123Re: I write type-safe generic data structures in C
#124The casting of the function type assumes that the item pointer type (e.g. Foo*) has the same representation as void*, which the C standard doesn’t guarantee (in standardese: the two types aren’t “compatible”). Calling the function with the converted type therefore constitutes undefined behavior. It also impacts aliasing analysis by compilers (see [0], incidentally), even if the pointer representation happens to be th…
This is addressed in the footnotes. casting is not the core of the type safety. Read the whole article.
int f0(int x) { return x; }
int f1(int x, int y) { return y; }
into a single function, so at runtime, (void(*)())f0 and (void(*)())f1 would compare equal. AFAIK, you are not guaranteed by the standard that functions of different signatures would, when their addresses are taken, result in different pointers, so it's not technically a bug... but it's quite surprising, and ruins certain tricks.Re: I write type-safe generic data structures in C
#125There's also the method used in the Linux kernel to embed the list information (struct list_head) within the type specific struct. https://kernelnewbies.org/FAQ/LinkedLists
The naming of LIST_HEAD_INIT and INIT_LIST_HEAD is confusing to me.
Re: I write type-safe generic data structures in C
#126Earlier quoted context omitted.
The naming of LIST_HEAD_INIT and INIT_LIST_HEAD is confusing to me.
Not to mention that they insist on calling every entry of the list a "list head", which makes no sense (hysterical raisins, maybe?). The structure is made of a uniform loop of entries, one of which is used as the actual head & tail, or entry point into the structure.
See https://github.com/rustyrussell/ccan/blob/master/ccan/list/_...
Re: I write type-safe generic data structures in C
#127Earlier quoted context omitted.
Not to mention that they insist on calling every entry of the list a "list head", which makes no sense (hysterical raisins, maybe?). The structure is made of a uniform loop of entries, one of which is used as the actual head & tail, or entry point into the structure.
Yes, it's terrible, and the fact that their list_add takes parameters backwards from what one might expect, with no types to catch mistakes! See https://github.com/rustyrussell/ccan/blob/master/ccan/list/_...
Re: I write type-safe generic data structures in C
#128Earlier quoted context omitted.
This is incorrect. In a function definition, an empty list means it takes no parameters. 6.7.5.3 Function declarators > 14. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters.
"has no parameters" is not the same as "cannot take arguments". Defining `int main()` does not stop the runtime from passing the usual 3 arguments (typically named argc, argv, envp), it only means that no parameters are bound to those arguments. Technically it's no problem to have a C function ignore its arguments by not binding parameters. Way too many programmers seem to not understand the difference between parame…
Re: I write type-safe generic data structures in C
#129Earlier quoted context omitted.
Unless it is a popular system or common architecture, yes.
Could you show me an example of a micro controller still supported today which doesn't have a C++ compiler?