6 ms·
I'm a C programmer by day and I disagree with them, C is only simple if you're trying to do simple tasks with it. The very common thing I want to use in C is s
by ChrisRR 4y ago
I'm a C programmer by day and I disagree with them, C is only simple if you're trying to do simple tasks with it.
The very common thing I want to use in C is some sort of variable size string object. But no, I have to dynamically allocate a buffer that I know will be at least the right size for any text I ever put into it, or do I create a buffer that's the correct size for that string but re-alloc if I ever change it to a longer string. But then how do I store the buffer size? Do I want to create a struct that constains a point to the buffer and the length, or use sizeof() to calculate the string length? But then I can't use sizeof() if I pass that buffer into a function via a pointer. If I pass that string to a function is it being copied straight away or just storing the pointer so I can't change the string at a later date. I can't enforce copy semantics
And god forbid you ever forget to include space for the NULL
I just want a string I can dump some text in, I don't want to go searching for libraries, I don't want to have to consider allocation and copying and all that crap.
If I wrote half of my boilerplate C code in python it would look just as simple and beautiful (if not more)
- ChuckNorris89 4y ago>I'm a C programmer by day and I disagree with them, C is only simple if you're trying to do simple tasks with it. C gives you enough rope to shoot yourself in the foot. And rightfully so. It came out in a time when everyone was coding assembly. It's meant not to hold you back from doing voodoo with low-level stuff, therefore it won't hold your hand. Not very practical in the world of today when we've been spoiled by 'better' languages and you need to quickly ship stuff that mostly works without worrying about the little things, but at the time it was revolutionary.
- flohofwoe 4y ago> when everyone was coding assembly.. This was before my time, but I think it's a common misconception (only true for operating system development). When C was created, there was already Lisp, Cobol, Fortran, Algol, Simula, BASIC... and SmallTalk and Prolog were just around the corner - and most of those are much higher level than C).
- uranusjr 4y agoI think parent knows. A more accurate description would be everyone of the intended audience was writing assembly. Yes there are other languages of higher levels, but C was not invented to help their users. And since they are also not really what Rust targets either, IMO it’s reasonable to shorten it to drop the qualifier in this context.
- tourmalinetaco 4y ago[flagged]
- pjmlp 4y agoC was invented in the context of porting UNIX, while the world outside Bell Labs used something else, that is all there is to it.
- jacquesm 4y agoSure, but none of those were for systems programming which is squarely the domain that C was aimed at, case in point: the first thing that C was used to write was UNIX (before then it was BCPL and this was iirc before C even had structs which made that a very tricky job, once structs were in place it got a lot easier). Probably Don Hopkins has more knowledge about this.
- flohofwoe 4y ago> before C even had structs which made that a very tricky job... ...interesting that you mention that, I think that functions and structs are the essential 'core abstraction tools' that get you to at least 80% of any higher level abstractions that were invented since then, and this is exactly the reason why C is still quite popular. Its feature set is just enough to be considered a high level language which enables abstractions, but not more (especially no fads and fashions that came and disappeared again).
- pjmlp 4y agoC23 has lots of stuff into it, except improved safety.
- jacquesm 4y ago> C gives you enough rope to shoot yourself in the foot. If this was intended to illustrate the unexpected consequences of undefined behavior it succeeded remarkably well!
- flohofwoe 4y agoUndefined Behaviour was a very late 'addition' to C, it only became necessary when C was standardised around 1990. And only after two more decades passed, UB became an actual problem when compiler vendors decided that it's fine to exploit it for optimization tricks.
- Brian_K_White 4y agoDid you miss their point? They merely used UB, correctly, as a term we all do recognize today. I will utterly kill all humor by explaining it: They made a funny observation about a thing that happens. The thing that happens is (today) called UB. The funny observation is that that comment kind of exhibited the outward appearance of what the effects of UB could look like. It began reciting one metaphore, "enough rope to hang yourself" but mid-way unexpectedly switched to a different metaphore "shoot yourself in the foot", producing a combined invalid nonsensical output. As though a program suffered some UB in the routine for looking up and printing metaphores. The comment author might have done it on purpose. Maybe they intended to make exactly that joke. The history of the term UB has no more bearing than the history of any of the other words used.
- Panzer04 4y ago“Decided that it’s fine to exploit it for optimisation tricks” is a poor characterisation. The reality is, if you define particular behaviours you will harm performance in some cases. If you define how something in particular should happen, then all architectures will need to implement that, regardless of their underlying semantics. eg. C leaves the case of exceeding the size of an int undefined. In most cases it has a predictable effect on modern, mostly similar architectures but that is by no means guaranteed, and forcing an architecture to calculate overflow a particular way seems like a negative. That being said, everyone has a pet example of a compiler doing some really odd and deep optimisations - I suspect that’s mostly due to successive layers and optimisers adding up to have unexpected effects, rather than a deliberate effort by compiler writers - but I’m no expert on the matter.
- coldtea 4y ago>It came out in a time when everyone was coding assembly Expect to hear from @pjmlp on this!
- krinkatt 4y agoI have something like this that serves me well: struct strbuf { size_t cap, len; char *str; }; void sb_setf(struct allocator *a, struct strbuf *sb, const char *fmt, ...); void sb_appendf(struct allocator *a, struct strbuf *sb, const char *fmt, ...); // have other convenience functions for formatting fixed point values like "prefix AAA.BBB suffix" ("voltage: 7.23 V") // special helpers for dates, times, etc. Just keep building that library up and you'll have growable buffer, strings, lists, hashmap (uintptr -> uintptr is all you need in 99% of cases I've found, maybe some helper functions for string key -> void * built ontop of uintptr->uintptr) + replace/rewrite the standard library to operate on these types instead and you're good to go.
- Someone 4y agoThat works until you want to use code from somebody else who also has something like that that serves them well, but is slightly different. If you’re extremely lucky, things will compile and work. If you’re just lucky things won’t compile, and you’ll have to write conversion functions (or macros). If you’re unlucky, there will be subtle differences, likely poorly documented, between the libraries, and code will compile but have subtle bugs. Of course, other languages have that problem, too, but at the higher level of json parsers or graphics libraries, not at the basic level of strings, lists, or maps.
- coldtea 4y agoCould even use something like Gnome's GLib
- coldtea 4y ago>The very common thing I want to use in C is some sort of variable size string object. But no, I have to dynamically allocate a buffer that I know will be at least the right size for any text I ever put into it, or do I create a buffer that's the correct size for that string but re-alloc if I ever change it to a longer string. But then how do I store the buffer size? As a C programmer shouldn't you have a library abstracting all this by now? Either your own or one of the dozens available, including pascal-style strings?
- jacquesm 4y agoIt's funny how both C and LISP programmers seem to suffer from NIH to the point that they'll roll their own just for the heck of it rather than to first see if there is a library that they can use. The long term cost of those decisions as well as the number of really bad bugs (and security issues) that can be traced back to one-off code is likely much larger than the same figure for well used libraries. But it all sort of evens out whenever a bug in such a library is found because then it is so widespread that lots of systems will suffer. Weird how that works.
- coldtea 4y ago>It's funny how both C and LISP programmers seem to suffer from NIH to the point that they'll roll their own just for the heck of it rather than to first see if there is a library that they can use. Well, not sure about the LISP programmers, but C programmers have a good reason: they work under different environments (from embedded to Windows, legacy UNIX, the latest Ubuntu, ...) and also have different needs, regarding allocation, string management, etc. So one-size-fits-all lib might not cut it for everybody. It can also be as simple as having an inherited codebase which uses something else. Still, there are popular string libraries, and C programmers do use them when they can.
- kaba0 4y agoWhat exactly is a problem with C++’s strings, or especially Rust’s? Everything you mentioned can be controlled as explicitly as you want. The only problem is C is simply not expressive enough to have proper abstractions like that.
- tpoacher 4y ago> But then I can't use sizeof() if I pass that buffer into a function via a pointer. Obviously, this isn't necessarily an improvement, but in theory you could do this: size_t getlength( int m, char (*p) [m] ) { return sizeof *p; } where you'd be calling it like this: char mystring[] = "Hello"; getlength( sizeof mystring, &mystring ) But then you're back in "having to pass the length as a separate parameter" territory, I guess. (but at least it's the length of the array here, not just the zero-terminated component, which is what you wanted).