Opinion: Personally, because I strive to learn more than to be "productive", I prefer languages that force the author to write her own libraries. As I see it, the alternative is languages that discourage this, effectively coercing the author to use other people's libraries, the quality over which she has no control.
Opinion: For me, the bad part is that there are so many poorly thought out C functions in the wild (even including the "standard" ones); the good part is that the C language encourages authors to write their own libraries.
Given the choice, I still prefer assembly to C. I guess this is because I prefer to write small programs; perhaps I am not smart enough to write large ones.
I prefer not to reinvent the wheel when I know my implementation won't be any better, or if I were able to make a better wheel, that will be time spent that I wasn't reinventing the carriage.
Implicit conversion between vectors and pointers should have never happened. I don't get why people find so hard to write &vector[0] for those cases where a pointer is needed.
Also if other languages, for other OS, older than C could do bound checking elision, C not doing it was only saving work for the compiler developer.
The requirement for a cast would be better, because that's the existing notation for explicitly requesting conversions that are identified as unsafe. I.e.
char array[42];
char *p = array; /* error, implicit conversion */
char *q = (char *) array; /* OK */
char *s = &array[0]; /* Sneaky: OK, without a cast */In any way, for me the right way of doing systems programming is the way of Mesa, Modula-2 and many others.
C was already bad in the 70's.
It didn't teach me enough to recognize the silliness in C.
I believe that this is an aspect of C popularity that hasn't received a lot of recognition. Programmers were sucked away from cleaner languages into C, because the users of the cleaner languages had neglected to acquire the body of rationalizations for why those languages are that way which could have helped them stick.
C looked good in naive ways. "Hey, look at all the things you can easily do with memory and pointers! Wow, look at that slick syntax: you can stuff several increments and an assignment into an expression, and use that as the test of a loop, ... man I'm never writing foo := foo + 4; again!"
Modula 2's memory management is basically malloc/free though. While the language could save you from array overruns, it is basically defenseless against leaks and use-after-free bugs, as well as uses of unchecked null pointers under OOM:
See:
http://www.modula2.org/reference/isomodules/isomodule.php?fi...
Look, the allocator works with generic pointers, has an explicit DEALLOCATE, and ALLOCATE returns NIL when there is no memory!
Modula 2' standard also has a SYSTEM module which adds C-like things: pointer arithmetic, casting and whatnot.
http://www.modula2.org/reference/isomodules/isomodule.php?fi...
Is that just "C envy", or is there perhaps need for those things, know what I mean?
Fortunately on the same year I got to learn C++, which allowed me to use most of the features I already knew from Turbo Pascal, alongside better safety if cared about it.
Eventually I only used pure C when required to do so at the university and on my first job after the university. Everywhere else the choice between both languages was always C++.
Regarding C, when coding in it, I always adopted a Turbo Pascal style by using translation units as if they were modules. With data structures designed as ADTs, without any direct access to its internals, defensively programming and eventually with a little bit of design by contract.
> Modula 2's memory management is basically malloc/free though. While the language could save you from array overruns, it is basically defenseless against leaks and use-after-free bugs, as well as uses of unchecked null pointers under OOM:
Yes, but there is already a bit list of errors that Modula-2 and similar languages saves one from:
- Buffer overruns (unless disabled, of course)
- Out parameters being null
- Implicit conversions of enumerations into integers
- Implicit conversions between numeric types
- Strings without terminating null
> Is that just "C envy", or is there perhaps need for those things, know what I mean?
Of course those features are needed in systems programming, but there is a big difference being safe by default and making explicit use of unsafe code, or just being unsafe everywhere.
For example, in Modula-2 if a module imports SYSTEM you already know that module is doing something fishy. In Oberon and Modula-3, like .NET, one could forbid unsafe modules from being loaded.
Whereas in C, even code that looks harmless can be doing strange things to the memory state.
strndup performs identical to strncpy except that it always terminates the destination string. (https://www.gnu.org/software/libc/manual/html_node/Copying-a...)
A grail shelf that wasn't intended as a booby trap would contain one cup, the right one.
/sarcasm
Then again "your C code is valid C++ code!" was perhaps the biggest selling point of C++ when it came out.
And no, std::string is decidedly not a proper "string class".
People often complain about the lack of a real "string class" in the standard C++ library. Well, guess what? No language today really has primitives that handle unicode absolutely perfectly, and there's still intense debate about what they should be doing with respect to encodings, length() functions etc.
Maybe the answer is that Unicode itself should be simplified so that every word in language has one representation in any particular encoding.
std::string is an embarassement. It's both bloated (why, we need to have both iterator-based and index-based access interfaces!) and lacks basic string manipulation functionality, it's encoding-unaware.
- It has all the string manipulation capability of the C standard library
- Being encoding unaware was probably a blessing given how unicode has evolved since std::string was introduced (20-30 years ago?)
If you want to use std::string operations on an array of characters that you don't own or that are part of an indivisible larger structure, you're out of luck.
It's not difficult to craft a slice-like replacement, but range types will be most welcome when they finally hit the standard.
http://en.cppreference.com/w/cpp/experimental/basic_string_v...
I personally now avoid C as much as possible.
People are just as likely to migrate to another language (Rust? Go? Even C++) as upgrade the old C code.
I don't think, that you can discontinue strcpy and co.
The C++ standard seems to get much more attention than C. C seems to be the step-daughter of programming languages, but still so many projects rely simply on standard C (and not C++).