3 ms·
> A very basic use case that shows up all the time everywhere, especially in systems programming, is that I have an array of items and I want to pass it to some
by jstimpfle 5y ago
> A very basic use case that shows up all the time everywhere, especially in systems programming, is that I have an array of items and I want to pass it to some library.
My thinking is this. Either a library function cares about what type of data you pass to it because it is designed to do some operation on it - then it will accept only a specific type, like "void func(Foo *foos, int count)". Or, the function does not care about the type of data but just wants to send it somewhere else. In this case, you can pass a void-pointer + size to it.
Interfaces like sorting functions can be seen as exceptions under the umbrella term "container library". Like the qsort() example, usually all you need is a few metrics for the data type - size, maybe alignment - and at most a few "method calls" - equality, simple get/set operations - and that's it. For all I can say these situations are not very common in systems programming, at least not for what I do. This stuff tends to come up in application level programming. It's definitely very common in my Python scripts. When it does come up in systems occasionally, a vtable struct is a good way to deal with the situation generically. In the qsort() case, the function pointer can be passed directly.
> 1. The library only accepts arrays of some specific type (e.g. int[]). If you have some other type, you have to find some way of converting to the type known in the library - in O(n) time.
Considering how computers work, I don't think it is much of a constraint to assume that arrays are of the form "Foo *foos". Coincidentally C _does_ have builtin "generics" for arrays of things, and real machines do have assembly instructions to quickly compute addresses based on hardcoded element size.
> (and of course, it's less safe, since instead of passing an int, you have to pass void* + sizeof(int), potentially getting them mixed up).
There is little real chance of getting them mixed up. If you actually run the code you will notice.
- unionpivo 5y ago> void-pointer + size to it How do I make sure they always stay in sync ? (adding removing elements) Because the ever increasing number of CVE's where brilliant programmers who screw this up, says doing this manually is prone to error. Sure you could do everything without generics. But its a lot more error prone. Generics can in addition with other language construct provide better safety. Generics also provide a tradeoff, that library code is more complicated, but its usage its easier to read.
- jstimpfle 5y agoYou don't. A pointer is a pointer, an int is an int. Memory is memory. Dynamic Arrays that support "adding or removing" elements are a high-level feature that don't mesh well with direct memory manipulation. If you are really really concerned you can try to code in Rust with its ownership tracking system. Otherwise, try to write simple enough code and test it as good as you can. You can use a language or compiler switch that at least supports "fat pointers" for implicit bounds checking, but this won't deal with reallocations. But in general "systems programming" means "buffer processing" i.e. a lot of "streaming" and most buffers are short lived - they are never overwritten and you drop them soon after they were created - or they never change in size. (reallocation incurs unnecessary copies, and there are many good reasons to chunk large data sets up into fixed-width sizes). All this makes "stay in sync" very much a non-problem. I haven't had to worry about this in years. It's almost an academic exercise that only exists to prove that we need garbage collection ;-) > Because the ever increasing number of CVE's where brilliant programmers who screw this up, says doing this manually is prone to error. If you code in a memory unsafe language like C, things can go horribly wrong and your code can be exploited. If you code in a memory safe language, you can end up with horribly slow and unmaintainable code and you might still be exploited. > Generics can in addition with other language construct provide better safety. Better than using a hash table with generics, is not using a hash table at all...
- ncmncm 5y agoOr, best, not even programming at all? Or, in practice, hiring somebody who actually understands how to program, understands what makes a library or language a good choice, and understands how to get the most value from both, without insane blinders.