6 ms·
I fully understand that sentiment. For several years now, I have also felt the strong urge to develop something in pure C. My main language is C++, but I have n
by lqet 2y ago
I fully understand that sentiment. For several years now, I have also felt the strong urge to develop something in pure C. My main language is C++, but I have noticed over and over again that I really enjoy using the old C libraries - the interfaces are just so simple and basic, there is no fluff. When I develop methods in pure C, I always enjoy that I can concentrate 100% on algorithmic aspects instead of architectural decisions which I only have to decide on because of the complexity of the language (C++, Rust). To me, C is so attractive because it is so powerful, yet so simple that you can hold all the language features in your head without difficulty.
I also like that C forces me to do stuff myself. It doesn't hide the magic and complexity. Also, my typical experience is that if you have to write your standard data structures on your own, you not only learn much more, but you also quickly see possibly performance improvements for your specific use case, that would have otherwise been hidden below several layers of library abstractions.
This has put me in a strange situation: everyone around me is always trying to use the latest feature of the newest C++ version, while I increasingly try to get rid of C++ features. A typical example I have encountered several times now is people using elaborate setups with std::string_view to avoid string copying, while exactly the same functionality could've been achieved by fewer code, using just a simple raw const char* pointer.
- chronogram 2y agoVariety is good. I got so used to working in pure C and older C++ that for a personal project I just started writing in C, until I realised that I don't have to consider other people and compatibility, so I had a lot of fun trying new things.
- brucehoult 2y agoTry doing C with a garbage collector ... it's very liberating. Do `#include <gc.h>` then just use `GC_malloc()` instead of `malloc()` and never free. And add `-lgc` to linking. It's already there on most systems these days, lots of things use it. You can add some efficiency by `GC_free()` in cases where you're really really sure, but it's entirely optional, and adds a lot of danger. Using `GC_malloc_atomic()` also adds efficiency, especially for large objects, if you know for sure there will be no pointers in that object (e.g. a string, buffer, image etc). There are weak pointers if you need them. And you can add finalizers for those rare cases where you need to close a file or network connection or something when an object is GCd, rather than knowing programmatically when to do it. But simply using `GC_malloc()` instead of `malloc()` gets you a long long way. You can also build Boehm GC as a full transparent `malloc()` replacement, and replacing `operator new()` in C++ too.
- dlisboa 2y agoWhich GC is that you’re using in these examples?
- School-Cotton 2y agoI'm not OP but the most popular C GC is Boehm's: https://www.hboehm.info/gc/ https://www.hboehm.info/gc/
- kokada 2y agoI think one of the nice things about C is that since the language was not designed to abstract e.g.: heap is that it is really easy to replace manual memory management with GC or any other approach to manage memory, because most APIs expects to be called with `malloc()` when heap allocation is needed. I think the only other language that has a similar property is Zig.
- irq-1 2y agoOdin has this too: > Odin is a manual memory management based language. This means that Odin programmers must manage their own memory, allocations, and tracking. To aid with memory management, Odin has huge support for custom allocators, especially through the implicit context system. https://odin-lang.org/docs/overview/#implicit-context-system https://odin-lang.org/docs/overview/#implicit-context-system
- kokada 2y agoInteresting that I was thinking of a language that combined Zig and Scala to allocate memory using implicits and this looks exactly what I was thinking. Not that I actually think this is a good idea (I think the explicitly style of Zig is better), but it is an idea nonetheless.
- 59nadir 2y agoA lot of our Odin procs take an allocator as a required argument specifically so they force you to choose one at the call site, because yes, often you want it to be explicit.
- bsenftner 2y agoAbout 16 years ago I started working with a tech company that used "C++ as C", meaning they used a C++ compiler but wrote pretty much everything in C, with the exception of using classes, but more like Python data classes, with no polymorphism or inheritance, only composition. Their classes were not to hide, but to encapsulate. Over time, some C++ features were allowed, like lambdas, but in general we wrote data classed C - and it screamed, it was so fast. We did all our own memory management, yes, using C style mallocs, and the knowledge of what all the memory was doing significantly aided our optimizations, as we targeted to be running with on cache data and code as much as possible. The results were market leading, and the company's facial recognition continually lands in the top 5 algorithms at the annual NIST FR Vendor test.
- zaphirplane 2y agoSounds like they know what they are doing. How is using c++ with only data classes different from using c with struct
- porridgeraisin 2y agoSlightly better ergonomics I suppose. Member functions versus function pointers come to mind, as do references vs pointers (so you get to use . instead of ->)
- bsenftner 2y agoYeah, slightly better ergonomics. Although we could, we simply did not use function pointers, we used member functions from the data class the data sat inside. We really tried to not focus on the language and tools, but to focus on the application's needs in the context of the problem it solves. Basically, treat the tech as a means to an end, not as a goal in itself.
- relaxing 2y agoNamespaces are useful for wrapping disparate bits of C code, to get around namespace collisions during integration.
- rossant 2y agoI completely agree with this sentiment. That's why I wrote Datoviz [1] almost entirely in C. I use C++ only when necessary, such as when relying on a C++ dependency or working with slightly more complex data structures. But I love C’s simplicity. Without OOP, architectural decisions become straightforward: what data should go in my structs, and what functions do I need? That’s it. The most inconvenient aspect for me is manual memory management, but it’s not too bad as long as you’re not dealing with text or complex data structures. [1] https://datoviz.org/ https://datoviz.org/
- maccard 2y ago> A typical example I have encountered several times now is people using elaborate setups with std::string_view to avoid string copying, while exactly the same functionality could've been achieved by fewer code, using just a simple raw const char* pointer. C++ can avoid string copies by passing `const string&` instead of by value. Presumably you're also passing around a subset of the string, and you're doing bounds and null checks, e.g. const char* Buf = "Hello World" ; print_hello(Buf, 6); string_view is just a char* + len; which is what you should be passing around anyway. Funnily enough, the problem with string view is actually C api's, and this problem exists in C. Here's a perfect example: (I'm using fopen, but pretty much every C api has this problem). FILE* open_file_from_substr(const char* start, int len) { return fopen(start); } void open_files() { const char* buf = "file1.txt file2.txt file3.txt"; for (int i = 0; i += 10; ++i) // my math might be off here, apologies { open_file_from_substr(buf + i, buf + i + 10); // nope. } } > When I develop methods in pure C, I always enjoy that I can concentrate 100% on algorithmic aspects instead of architectural decisions which I only have to decide on because of the complexity of the language I agree this is true when you develop _methods_, but I think this falls apart when you design programs. I find that you spend as much time thinking about memory management and pointer safety as you do algorithmic aspects, and not in a good way. Meanwhile, with C++, go and Rust, I think about lifetimes, ownership and data flow.
- wruza 2y agoI also like that C forces me to do stuff myself I never liked that you have to choose between this and C++ though. C could use some automation, but that's C++ in "C with classes" mode. The sad thing is, you can't convince other people to use this mode, so all you have is either raw C interfaces which you have to wrap yourself, or C++ interfaces which require galaxy brain to fully grasp. I remember growing really tired of "add member - add initializer - add finalizer - sweep and recheck finalizers" loop. Or calculating lifetime orders in your mind. If you ask which single word my mind associates with C, it will be "routine". C++ would be amazing if its culture wasn't so obsessed with needless complexity. We had a local joke back then: every C++ programmer writes heaps of C++ code to pretend that the final page of code is not C++.
- chasd00 2y agoMost of the embedded world is still C, if you want to write C that's probably the place to find a community.
- zafka 2y agoI agree with this sentiment. My first gig was telecom, and I wrote in a pascal like language called CHILL, but found out my forte was debugging and patching and ended up doing a fair amount of assembly code that would get applied to live systems. The decade plus I spent in medical devices, I used C and assembly. The thing is, if you own all the code and actually understand what it is supposed to do, you can write safe code.
- hgs3 2y agoAgreed. C, Go, Python, and Lua are my go-to languages because of their simplicity. It's unfortunate, but in my opinion, most mainstream languages are needlessly complex. In my experience, whether it's software architecture or programming language design, it's easy to make things complicated, but it takes vision and discipline to keep them simple.
- pansa2 2y ago> C, Go, Python, and Lua are my go-to languages because of their simplicity One of these things is not like the others! Python's complexity has been increasing rapidly (e.g. walrus operator, match statement, increasingly baroque type hints) - has this put you off the language at all?
- seanw444 2y agoI started programming with Python years and years ago. My journey has led me to preferring low-level languages (currently in a Zig bout), and revisiting Python has been a disappointing experience. Not necessarily bad, but instead of focusing efforts where it really matters, such as eliminating GIL, they seem to be focused on adding new syntactic sugar.
- hgs3 2y agoPython's complexity has been increasing since Guido stepped away and it is off-putting. The language is still nowhere near as complex as Ruby or others, but I am keeping my eyes open for alternatives.
- DeathArrow 2y agoI like the idea of using C++ as C. I began disliking OOP, inheritance and encapsulation, heavy usage of GoF patterns and even SOLID. They promise easy to understand, easy to follow, easy to maintain, easy to change, easy to extend code and a good productivity but the effect is contrary, most of the times. I like functional programming and procedural programming. Fits better to how I think about code. Code is something that takes data and spits data. Code shouldn't be forced into emulating some real life concepts.
- deleted 2y ago[deleted]