4 ms·
It seems to me C/C++ has always had problems. K&R C had weird stuff like char pointers used to point to anything. And modern C++ has odd complexities like what
by johan_larson 10y ago
It seems to me C/C++ has always had problems. K&R C had weird stuff like char pointers used to point to anything. And modern C++ has odd complexities like what Scott's article illustrates.
Was there ever a Goldilocks moment when C was just right?
- Roboprog 10y agoC works great, as an alternate to assembler, to bootstrap unix up on meager, 80s style, hardware. Based on things like the shell tools and languages like awk (and other related descendants), I don't think even the unix creators meant for much application level work to be done in C, though, but by assembling components in higher level languages. Try telling that to The Management and all the macho/masochistic Real Programmers, though. Bounds checking? Memory management? (names you can identify to the left of the types, like in Algol, instead of to the right?) That's for sissies!
- pjmlp 10y agoWorse is that even the C creators saw the danger of using C without computer assisted validation and created lint in 1979. https://www.bell-labs.com/usr/dmr/www/chist.html https://www.bell-labs.com/usr/dmr/www/chist.html Yet to this day, many still don't use any sort of static analysis tool.
- Roboprog 10y agoTo be honest, I seldom used lint, either, when I was starting out (although I suppose I cheated by using the Borland IDE in the early 90s). However, when using gcc in the mid to late 90s, it was just too easy to tack on -Wall (enable all warnings) to the options. No real excuse not to always check things, at that point.
- chubot 10y agoI'm struggling with this too... I'm implementing a shell, and on the one hand I've been looking at ancient C code in bash, dash, zsh, mksh, etc. That's clearly not the right way to do it, with raw strings, pointers, and globals everywhere. It's ridiculously verbose and error prone. All recursive parsers in C seem to use setlongjmp for error handling. They have weird memory management with stack allocated strings and globals too, because memory management in C is such a pain. I tend to like "C with classes". When I started working at Google, the C++ style was a breath of fresh air over what I had seen in the game industry (this was in 2005, so C++ was in a very different state). It was very much C with classes: no exceptions, no iostreams, no operator overloading, no default copy constructors or assignment, in/out params, etc. (Lately it has been trending toward "modern C++", albeit with custom internal libraries for errors and such) Then C++ 11 came out -- you really can't do without auto and range for loops. It looks like strongly typed enums are useful, and some STL stuff. For recursive parsers, exceptions instead of setlongjmp seems useful too (setlongjmp doesn't work with destructors AFAIK). I'm scared of R-Value refs and move semantics -- I don't know anything about those. I guess my point is that it's 2016 and it's hard to know if there was a goldilocks moment. Google was using a restricted dialect of C++03 which I think was pretty great and built a lot of real software, but it's hard to say that C++11 didn't add anything useful. I'm sure the Google style diverges pretty wildly from Bjarne's new effort of C++ core guidelines, which I need to look into more: https://google.github.io/styleguide/cppguide.html https://google.github.io/styleguide/cppguide.html https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC... It seems like the LLVM codebase really knows what it's doing in terms of C++, which makes sense, but honestly it's fairly complex for what I want to do. So I think we are just stuck with all these local dialects, which makes code reuse a problem.
- ant6n 10y agoI'm not quite sure what you mean by 'goldilocks moment', but I think C++11 was it. Ever since then, the language has had a nice balance of high level abstractions at low level performance. (Theoretically it actually got faster due to move semantics)
- chubot 10y agoThe parent was asking the goldilocks question -- was there ever a point where C++ was not too complex like modern C++, e.g. this {} issue, but had enough features (contrast with C, which doesn't have enough features for many applications). I don't think there was such a moment. Apparently move constructors were a de-optimization in the case of std::vector. As far as I remember, it's related to iterator invalidation and move semantics making small-size optimization impossible (e.g. inlining small vectors into the object itself rather than having another pointer and heap allocation). I'm pretty sure it's in this video: https://www.youtube.com/watch?v=vElZc6zSIXM https://www.youtube.com/watch?v=vElZc6zSIXM Although it's debatable how big a deal this is, it's a good example of the point. People like "C with classes" because they can read the source and kind of figure out what code is generated. They can reason about locality. Although I don't consider myself an expert C++ programmer, if I can't reason about the consequences of move constructors on std::vector, which is a fundamental and relatively simple data structure, then the language is already getting into "surprising" territory. I would have never figured out that de-optimization unless I heard it in a video. On a related note, I wish that return value optimization had better syntax -- that would make move semantics unnecessary in a lot of cases. On the other hand, reasoning about the generated code is already a lost cause because assembly code is so complicated now. We now have to live in a world where we can never fully understand our tools.
- placidbox 10y agoAt what point is it mentioned in the video? AFAIK small optimization on std::vector was already invalid since .swap() needed to keep existing references/iterators valid, couldn't throw or call copy constructors/assignment. RVO being transparent would be nice, though. There's a proposal somewhere to make it guaranteed in some circumstances, but it's still fairly opaque when reading code
- pjmlp 10y agoC was already bad when it was born, comparing with what Burroughs was doing in Burroughs B5000 in 1961, nowadays sold by Unisys ClearPath MCP. Or other similar languages on those days, like Concurrent Pascal on Solo OS (1975). When I learned C in 1993, it seemed quite poor compared to my Turbo Pascal 6.0 type safety and respective language features.
- bitL 10y agoThe main advantage of C was that it allowed you to type stuff super fast comparing with Pascal ( {} instead of Begin .. End etc.) and had some very handy shortcuts for often used operations like ()?:, ++, --, += etc. Less verbose language, less need to type syntactic structures. You could basically keep the flow of what is in your mind with the progress on your keyboard and forget about typing it; you were simply assembling stuff in your mind and at a rapid face making it happen on a computer. Something similar you can now probably experience with Go, sometimes Scala.
- pjmlp 10y agoTyping fast usually doesn't lead to working programs that solve what is actually the customer's problem. Software engineering isn't about "keeping the flow", rather about achieving the quality, deliverables and desired outcomes required by the users of the software.