Live data from Hacker News

50 years of C, the good, the bad and the ugly [video]

streaming.media.ccc.de

221–230 of 257 posts

Re: 50 years of C, the good, the bad and the ugly [video]

#221

Earlier quoted context omitted.

C null terminated strings are not magic. Protocols between the sender and receiver have to be defined. You face exactly the same problem regarding byte order, size consideration and marshalling with C strings. You are basically arguing that C strings are a good default because they are the default. If they were something else, well, we would have saner FFI in a lot of place. C strings are a terrible default. They are…

> You face exactly the same problem regarding byte order, size consideration and marshalling with C strings. Not char/byte C strings. You might be thinking of wchar_t strings. > Mishandle the null char for any reason and you now face a serious security issue. With what string data structure can applications peak into and mishandle an implementation detail and not risk creating a security problem? Same you have a stru…

> Not char/byte C strings. You might be thinking of wchar_t strings.

No I’m talking about the classic byte arrays C pretends are strings. If the receiver you are talking to is not expecting a chain of bytes where each byte is a character and one special value means the chain is over, well, you will have to transform what you are sending to what your receiver is expecting.

Re: 50 years of C, the good, the bad and the ugly [video]

#222

Earlier quoted context omitted.

There is no elegance there. Casting to void is not a plus. That’s just C having no proper type system. Function pointers as an elementary form of closures, come on, what’s next? Closures are defined by capture. It’s nearly as fun as pretending C as coroutines because of setjmp . How can a statement like C being semantically poor even be seen as controversial? For god sake, we are talking about a language which semant…

Much of what you say is true. But I came to C from Pascal. Pascal circa 1982 was unusable without all the numerous extensions each vendor tacked on. C worked out of the box. I could get things done in C without constantly fighting the Pascal and Fortran compilers of the day. This was true despite the terrible C compilers of that time.

I remeber that Small-C and RatC were hardly usefull without tons of inline Assembly.

As proven by books like "A book on C" from 1984 (Robert Edward Berry and B. A. E. Meekings).

Re: 50 years of C, the good, the bad and the ugly [video]

#223
post #122

Earlier quoted context omitted.

It depends on how you define your language semantics. If you choose 2's complement wraparound semantics, which is what nearly all CPUs in the world have standardized on, there is nothing for the compiler to do. It's a pure operation, a single instruction, and can be constant-folded, strength-reduced, CSE'd, moved, dead-code-eliminated, etc. If you want a different semantics at the source level, e.g. overflow is an ex…

> If you want a different semantics at the source level, e.g. overflow is an exception, then the compiler needs to emit additional code. Yes, and which is exactly what I hinted at with my question to your comment. With the HW we have today, implementing such semantics without an extra hit is not possible and which is why I thought your comment wasn't completely fair but coming from more theoretical stance.

Checking for overflow is basically adding a conditional branch (usually to out-of-line code) after arithmetic. It's very cheap, almost free, if there are enough execution units, I-cache isn't a bottleneck, etc etc. But yeah, it is theoretically an overhead, which is why I avoided it for Virgil.

I suppose range analysis can eliminate many overflow checks, e.g. in counted loops, but it's not completely zero cost.

Re: 50 years of C, the good, the bad and the ugly [video]

#224

Earlier quoted context omitted.

What is your take on Perl and Ruby? They seem to be the two languages where the communities themselves talk the most about poetry and elegance.

Perl (5) I find quite complex, the opposite of C and Prolog. I suppose the elegance some find comes from packing lots of behavior into very few characters of code. When I want to code as art though, I prefer simpler, less "magical" tools. I've never used Ruby but from what I've seen I understand it to be similar to Perl in that regard.

I agree that perl can be complex, its feature list is longer than C. Trying to be artistic in it, to me, means trying to make it so my code reads as much like pseudo-code as is reasonably possible. At its best the users are able to read the business logic portions and understand what is going on.

Of course good naming and abstractions are of key importance, and comments and inline documentation are important finishing touches, which so many programmers don't seem to have the time for. It doesn't hurt that Larry Wall, the designer of perl, was a linguist. Perl was meant to be flexible and expressive.

And everyone knows that there's nothing worse to read than obfuscated perl. Perhaps some think that is artistic in a different way, to make the shortest and most unreadable program possible. Not my thing, personally.

Re: 50 years of C, the good, the bad and the ugly [video]

#225
post #20
post #5

Great talk. Borland should have rated a mention though, their C compiler really popularized C development on Windows.

Most sane Borland customers were using C++ alongside Object Windows Library, not raw C alongside Win16. Even Petzold embraced C++, even if superficially, "This third edition has several changes. First, all programs are now compilable with either the Microsoft or the Borland compiler. All make files are generic and use environment variables for compiler flags, link libraries, and so forth. Second, all programs are now…

One day later: some more thoughts on this, I think the biggest reason to pick Borland was bluntly put the price. There was simply nothing else that came even close to being that affordable and, more importantly, that would run on my relatively anemic machine. I was dirt poor back then, my computer didn't even have a case, it was essentially a motherboard and a power supply bolted to a steel frame of one of those office folder hanger carts (I don't know what those are called in English, but they were pretty common in the days of paper file folders). I just plugged cards into the top and a harddrive (a 20 MB MFM Seagate which cost as much as my car) was sitting loose on the same base with some cables to keep it connected to the motherboard. It was about as ugly as it could be but it worked and I was pretty happy with it.

Happy New Year by the way, if you are still up and reading this!

Re: 50 years of C, the good, the bad and the ugly [video]

#226

Earlier quoted context omitted.

> The biggest ones for me in Rust is that it disallows extending traits for types you don't own, and the lack of function overloading. Neither of those are required for the borrow checker or safety, but it's a philosophical design decision. The orphan rules are definitely necessary for coherence: otherwise, you could end up with a situation where two different crates try to implement the same trait for the same type,…

> The orphan rules are definitely necessary for coherence: ... and there would have to be some (likely unwieldy) mechanism to resolve that. I think Julia, D, Nim, and others show its possible and generally easy to work with open ended type systems. I think Haskell does as well? Though yes those come at the cost of possible conflict or user confusion, which is why I consider it a philosophical decision. It matches wit…

> I think Julia, D, Nim, and others show its possible and generally easy to work with open ended type systems.

Sorry, could you give an example of this? I can't find any way to extend existing types in those languages with some brief Googling.

> It matches with the decision to not allow user code to use trait specializations in stable despite the stdlib having it.

Keeping specialization unstable is much more a practical decision than a philosophical position: if they could, they would've stabilized it years ago. The problem is that specialization very quickly becomes unsound in combination with lifetimes. The compiler erases all lifetimes on types after checking them, since monomorphizing a new type for each lifetime would lead to an exponential explosion (this can't be changed at this point without redesigning the language). Therefore, users must not be able to specialize a trait impl on certain lifetime combinations (or certain lifetimes like 'static), since the compiler would have absolutely no way to tell which impl to use. And in turn, completely barring lifetime specialization becomes a daunting challenge with the existence of associated type projections and blanket impls. Specialization definitely isn't kept unstable just because they think users can't be trusted with it.

> Imports generally seem fine for controlling what gets used. Want a trait impl, import it into a module.

I don't think this would be compatible with blanket impls, since you couldn't just import every single potential impl in existence (and if you could, you'd run into conflicts). I suppose you could have a system of exporting impls, where to use a blanket impl you have to pass it another impl as input, but at that point you have new idiosyncratic system that would scare away users and would likely be far more noisy than a good newtype system.

> Unfortunately that means you can't define 'default' or 'clone' traits for a type. That prevents you from using derives on your newtypes as well. That means manually implementing clone, or serde which is a PITA.

If a foreign crate doesn't implement Default or Clone for its types, then how is the compiler supposed to derive it for your local newtypes? It can't just look into the foreign type's fields, if they aren't all public. Are you often having to work with fully public foreign types?

Overall, I get that the type system can be pretty frustrating as it stands today, but I don't see any better alternative than building better tools for defining newtypes.

Re: 50 years of C, the good, the bad and the ugly [video]

#227

Earlier quoted context omitted.

SafeC and CheckedC do nothing for temporal safety. Zig is in the same boat. There's not really a simpler alternative to Rust with the same featureset, even its direct predecessor Cyclone was in fact quite a bit harder to use. Rust itself is also improving very quickly and becoming easier to use over time.

Rust seems to have a lot of C++ influence to me, specifically later C++ where RAII and smart pointers became the norm. This makes sense that it came out of Mozilla, who have always had large C++ code bases.

This is honestly my biggest problem with Rust. C is a small language where the std libraries and language are defined in hundreds of pages. C++ last I checked in the latest standard was getting to almost 2000 pages.

Rust does not have a defined standard yet, but I suspect it also would be quite large.

Re: 50 years of C, the good, the bad and the ugly [video]

#228

Earlier quoted context omitted.

> You face exactly the same problem regarding byte order, size consideration and marshalling with C strings. Not char/byte C strings. You might be thinking of wchar_t strings. > Mishandle the null char for any reason and you now face a serious security issue. With what string data structure can applications peak into and mishandle an implementation detail and not risk creating a security problem? Same you have a stru…

> Not char/byte C strings. You might be thinking of wchar_t strings. No I’m talking about the classic byte arrays C pretends are strings. If the receiver you are talking to is not expecting a chain of bytes where each byte is a character and one special value means the chain is over, well, you will have to transform what you are sending to what your receiver is expecting.

If somebody's expecting something other than a C string then we unsurprisingly have gratuitous complications. If everyone agrees on the C string though, it just interoperates as-is. Code compiled for some 16-bit microcontroller can just shove the C string into its transmit buffer, and on the other end, code compiled for 64 bit big-endian Power PC receiver just uses it as-is.

Re: 50 years of C, the good, the bad and the ugly [video]

#229

Earlier quoted context omitted.

There is no elegance there. Casting to void is not a plus. That’s just C having no proper type system. Function pointers as an elementary form of closures, come on, what’s next? Closures are defined by capture. It’s nearly as fun as pretending C as coroutines because of setjmp . How can a statement like C being semantically poor even be seen as controversial? For god sake, we are talking about a language which semant…

Much of what you say is true. But I came to C from Pascal. Pascal circa 1982 was unusable without all the numerous extensions each vendor tacked on. C worked out of the box. I could get things done in C without constantly fighting the Pascal and Fortran compilers of the day. This was true despite the terrible C compilers of that time.

Pascal wasn't ready for real-world use because it came from an academic setting and was initially designed to run P-code in a VM. It's successor, Modula-2, fixed all of Pascal's issues and added a lot of great functionality.

Re: 50 years of C, the good, the bad and the ugly [video]

#230

Earlier quoted context omitted.

> Not char/byte C strings. You might be thinking of wchar_t strings. No I’m talking about the classic byte arrays C pretends are strings. If the receiver you are talking to is not expecting a chain of bytes where each byte is a character and one special value means the chain is over, well, you will have to transform what you are sending to what your receiver is expecting.

If somebody's expecting something other than a C string then we unsurprisingly have gratuitous complications. If everyone agrees on the C string though, it just interoperates as-is. Code compiled for some 16-bit microcontroller can just shove the C string into its transmit buffer, and on the other end, code compiled for 64 bit big-endian Power PC receiver just uses it as-is.

C is the biggest mistake in the software industry since the beginning of software. The people that worship C only do so because they haven't seen the better paths the software industry could have chosen.
Post reply on HN