4 ms·
> A common example of a harmful abstraction, in C and C++, is a typedef of a pointer to an opaque name. The typedef conceals, when you read code using it, that
by badsectoracula 5y ago
> A common example of a harmful abstraction, in C and C++, is a typedef of a pointer to an opaque name. The typedef conceals, when you read code using it, that the type is really a pointer, and so subject to all the excess operations provided for pointers in those languages. But one thing every C and C++ programmer always needs to know about a type they are working with is whether it is a pointer.
C (and C++) programmers only need to know if a type is a pointer if they are meant to know it is a pointer. Otherwise very often a foo_t is meant to be used via manipulation functions and it being a pointer or an integer or whatever else is a detail that the programmers do not need to care about. This is a very common approach for libraries when trying to make a shared library with a stable ABI, though it is also common when you want to isolate accessing the underlying data of whatever a "foo_t" represents to a single known module.
Often you see "foo_t*" instead of "foo_t" (with foo_t being an undefined struct) but with "foo_t" being unusable by itself it is always stored and passed around as a pointer and thus the same -incredibly few and irrelevant in practice- pitfalls would apply anyway, so in reality it all boils down to personal stylistic preference if you want to litter all those stars in a project or not. Personal preferences like that have nothing to do with youthfulness or even experience.
- ncmncm 5y agoI.e., you lack the experience to understand that concealing pointer semantics of a type is harmful.
- badsectoracula 5y ago> I.e., you lack the experience to understand that concealing pointer semantics of a type is harmful. I have been working with C codebases for decades and have more than enough experience thank you. You didn't really reply to what i wrote though.
- ncmncm 5y agoSuffice to say, there is way too much bad code out there, and we all pay.
- criddell 5y agoAre HANDLEs as used by Win32 an example of what you are talking about? They may be implemented as a pointer to something, but that's not how you use it.
- ncmncm 5y agoYes, HANDLEs are the worst kind of abstraction: they hide everything you need to know, and provide no corresponding benefit.
- Koshkin 5y agoBelieve me, you do not want to know what is hidden behind a HANDLE!
- mattgreenrocks 5y agoThe nice thing about a HANDLE is they can be a pointer to kernel space, a pointer to something in user space, or an opaque index into an internal table of managed resources. If it was a pure pointer, then 0 has to be avoided as it can be mistaken for "no value" by users. Of course, you replace that with knowing to check for INVALID_HANDLE_VALUE. IMO, HANDLEs are probably a bit too opaque for my taste, as you have to know what operations you should be using with them. I'd prefer opaque structs if I had to choose.
- ncmncm 5y agoThat is not, in fact, a nice thing. It is exactly what you would better have different types for, that implicitly do the right thing, and only ever do the right thing. HANDLE is the worst of all possible worlds.
- Koshkin 5y agoYou are not wrong; the problem is, "different types" are language-specific, whereas HANDLE is a primitive (machine-level) type that is not and thus can be easily used from any language.