10 ms·
Does anyone remember reading K&R for the first time? To me seemed like C was such a tight, perfect little design. Only thirty keywords, and simple consistent
by gerbilly 7y ago
Does anyone remember reading K&R for the first time?
To me seemed like C was such a tight, perfect little design.
Only thirty keywords, and simple consistent semantics.¹
When I first learned it, it was still pre ANSI, and you declared a function like this
int f(a)
char *a
{
}
The ANSI style function declaration was maybe the only innovation that came after that that significantly improved the language.
I remember in the late '80s knowing my compiler so well that I could tell you what the stack frame would look like pretty much anywhere in my code. It was awesome to have that level of familiarity.
Soon after that things started to get more complicated, and I did a lot of Java, and I never again felt as dialed in to those languages as the late 80s C that I started out with.
The K&R book is worth a read if anyone missed it. It's beautifully written. A far cry from the 'opinionated' copy that you often find on the Go website.
Personally, I don't think you can make similar claims about Go's design or the 'because I told you so' tone that surrounds it.
1: Yes, I know, undefined behaviour, but this is my post and this is how I feel about C.
- AlchemistCamp 7y agoI just started digging into C a few years ago and was struck by the same. It's amazingly simple and the only "flaw" that leaps out at me is the precedence of & and | being higher than comparison operators. Other than that, and maybe the macro system, everything frustrating about learning it was due to the frustration of dealing with the machine rather than anything C itself imposed on me.
- WalterBright 7y agoI love C, but it's biggest mistake is clearly the unstoppable decay of arrays to pointers: https://www.digitalmars.com/articles/b44.html https://www.digitalmars.com/articles/b44.html A mistake that C++ missed an opportunity to fix.
- wbl 7y agoArrays are for FORTRAN is I think the reason.
- gerbilly 7y agoI read the article you linked. It's too bad they didn't decide to pass a fat pointer with the array dimensions. But when the article implies that null terminated strings and the problems associated with them are caused by arrays decaying to pointers, I get more skeptical. I mean it's not as if arrays in C are bounds checked anyway, so how would that have helped implement strings any better? I guess you could have bounds checked them in the stdlib code, but you certainly wouldn't have gotten it for free just by knowing the array dimensions.
- WalterBright 7y ago> I mean it's not as if arrays in C are bounds checked anyway, so how would that have helped implement strings any better? I've written an awful lot of C code, and I have much experience with the D way which uses arrays instead of null termination. When I review a section of code consisting of strlen/strcat/strcpy/etc. I routinely find bugs in it, always centered around a mistake with the 0 termination. When the array bounds are available, the compiler can optionally insert array bounds checks. As for getting it for free, avoiding doing the strlen()'s is a big time saver.
- ChrisSD 7y agoC can be quite complex once you get into all the abstractions it's using. And even for newbies I think the whole syntax around pointers is unnecessarily confusing (or at least people are often confused by it in a way they usually aren't when learning assembly). Not to mention how many keywords and symbols are overloaded and depend on their context for meaning.
- AlchemistCamp 7y agoTo be fair, I never learned it in its heyday and even now, I've just worked on some toy utilities and an 8088 emulator. I've never used it for work or open source or anything "real".
- carterehsmith 7y ago>> C can be quite complex once you get into all the abstractions it's using. Perhaps you were referring to C++, or some newer C dialect? What I mean is, the K&R C had very few (if any) abstractions, other than those defined by preprocessor. Like, you could look a the C code and pretty much "see" what the assembly code would look like after compiler did its work.
- ChrisSD 7y agoYeah, on reflection you're right about that. At the time when the language matched the hardware the abstraction was much more literal. It was only when they diverged that optimizing compilers were needed and all the complexity was introduced in order to maintain the fiction that the hardware was still as simple as PDP-11.
- throwaway34241 7y agoThe modern aggressive undefined-behavior based optimizations ruins any remaining appeal of the "simplicity" of C for me. The extremely broad definition of undefined behavior may allow the compiler to, for example, silently delete explicit checks for signed integer overflow [1] among other things and still claim standards compliance, but I don't think that programming model can reasonably be described as simple. It many ways Go feels like an updated C. It retains most of the basic abilities of C, while cleaning up some things (headers, etc), having more basic libraries included, and choosing some defaults around things like out-of-bounds array access that are probably more appropriate for the majority of most programs (outside of particular hot loops, etc) in an era where software is often connected to the network and security is a bigger concern. [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475, http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- astrange 7y agoLots of programs don't need efficiency in "hot loops". You want efficient code size everywhere (usually smaller is faster), and realtime programs like games are CPU-bound everywhere not just in one loop. Undefined behavior is a great way to help the language help you; for instance, most loops look like infinite loops without it. All you need to do is test with ubsan to see if you're dynamically undefined anywhere.
- throwaway34241 7y ago>realtime programs like games are CPU-bound everywhere not just in one loop Isn't this a simplification? Even for games, I'd expect most often to be GPU bound, then memory bandwidth bound, and only then CPU bound. Although I get that the hot loop thing/10% rule is not universally true for every CPU bound program (especially after code has already been heavily optimized). But I'm not sure what you are disagreeing with. I didn't mean to totally deny the usefulness of UB in C++ (although I think the core rendering code of AAA games are more performance sensitive than "the majority of most programs"). I was just pointing out that C is certainly not as simple as it first appears, and many people new to it are not familiar with the rules around UB. Go's able to design around some of the performance aspects without UB (using the native word size for ints by default can help some of the signed integer stuff, range loops can elide bounds checks, etc), but probably can't generate as optimal code as C can without dropping to assembly language.
- lmm 7y agoCan't say I got that feeling at all. Smalltalk is a tight design. So is Lisp. So is Forth. So is APL. C's design just feels like a pile of... stuff. Arrays are almost but not quite the same as pointers. You can pass functions but not return them. There's a random grab-bag of control flow keywords, too many operators with their own precedence rules, and too many keywords given over to a smorgasbord of different integer types with arbitrary rules for which expressions magically upconvert to other ones.
- tx-0 7y agobut you can't pass functions in C, you can only pass pointers-to-functions... and you can return them too. the piles of stuff that C contains are the stuff of 20th century von Neumann architectures, the stuff that defines the undefined behaviors, and that's what has made C indispensible. I'm not saying C's perfect, but you can't swap it out without replacing what it did and does.
- fao_ 7y agoHi, I vouched for this comment, so people can see it. You're shadowbanned, it seems. I took a glance at your comments and I can't really see a reason for it, many of your comments are borderline but I've seen worse here by 'top rated' commenters.
- kazinator 7y agoThat's the same with languages that have first class functions. The code part is still passed by reference, not by copying around the machine code.
- axaxs 7y agoSame here. K&R C is probably still my favorite programming book. I will admit that most of the examples I had to stop and think about, they all seemed 'cleverly' written. But in each case, it gave me pause, and taught me a new, often simpler way.
- throwaway34241 7y agoThe 'K' in K&R actually wrote a book on Go, "The Go Programming Language". I haven't used it personally but it has good reviews, so it might be a good resource for people who are curious about Go and know they like that writing style.
- synthmeat 7y agoIt's a bit looser than whitebook, but it's still very much in the spirit of it. K really writes well.
- bitmadness 7y agoIt's excellent, highly recommend.
- tzs 7y agoAt the time it was written, there was a good chance that the person reading it would not be doing so at a computer. Their computer access was quite likely via a terminal on a time sharing system, that they had to share with others. They couldn't hog a terminal while reading a book and typing in examples from it. So books of that day where written so you could learn a lot just from reading the book and thinking seriously about the examples, and working out the exercises in your head or on paper It helped if every couple of days or so you could get some computer time and try out the things you learned, but it wasn't actually necessary. In the case of K&R, you could go through the whole book without touching a computer, and then one or two sessions afterwards trying things out could be enough to correct your misunderstandings. I wish more books were like that today. Nowadays, they assume you are a computer all the while you are reading the book, and often depend on that when writing the text.
- ryl00 7y ago> The ANSI style function declaration was maybe the only innovation that came after that that significantly improved the language. "const" as well (back ported from C++ ?). And being able to declare variables anywhere (instead of just at the beginning of a block)
- tom_ 7y agoWhat about aggregate literals, designated initializer syntax, _Generic, and thread.h?
- CalChris 7y agoI’d add the deprecation of register. Not an innovation but an improvement nonetheless.
- SilasX 7y agoInterestingly, the high level language you implement for the nand2tetris course has this constraint, which makes writing the compiler easier
- brian_cunnie 7y agoI took that course, too! I loved it. Learned more about computers than any other of the many courses I took.
- astrange 7y agoVariable-argument macros, function prototypes (well, modules would be better…), // comments, stdatomic instead of 'volatile' hacks, _Bool, aligned_alloc, …
- simias 7y ago>To me seemed like C was such a tight, perfect little design. Only thirty keywords, and simple consistent semantics. Except that clearly history showed that it wasn't enough, and we ended up with about 50 millions (and counting) different meaning for "static" for instance. I like C but its simplicity is almost by accident more than by design. It's pretty far from "perfect" in my book. There are so many weird features about the language that can bite you ass for no good reason. Why don't switch() break by default since it's what you want it to do the overwhelming majority of time (answer: if you generate the corresponding assembly jump table by hand "fall through" is the easiest and simplest case, so they probably kept it that way). Why do we have this weird incestuous relationship between pointers and arrays? It might seem elegant at first (an array is a pointer to the first element or something like that) but actually it breaks down all over the place and can create some nasty unexpected behavior. Why do we need both . and -> ? The compiler is always able to know which one makes sense from the type of the variable anyway. String handling is a nightmare due to the choice of using NUL-terminated strings and string.h being so barebones that you could reimplement most of it under an hour. Some of the operator precedences make little sense. Writing hygienic macros is an art more than a science which usually requires compiler extensions for anything non-trivial (lest you end up with a macro that evaluates its parameters more than once). Aliasing was very poorly handled in earlier standards and they attempted to correct that in more modern revisions while still striving to let old code build correctly and run fast. So you have some weird rules like "char can alias with everything" for instance. Good luck explaining why that makes sense to a newbie without going through 30+ years of history. The comma operator. Undefined function parameter evaluation order. I suspect that with modern PL theory concepts you could make a language roughly the size of C with much better ergonomics. I'm also sure that nobody would use it.
- timClicks 7y ago> (answer: if you generate the corresponding assembly jump table by hand "fall through" is the easiest and simplest case, so they probably kept it that way) If this is true, then that makes perfect sense. C was attempting to look after its target market: assembly programmers.
- Boxxed 7y ago
- maxxxxx 7y ago"The K&R book is worth a read if anyone missed it. It's beautifully written." Agreed. I read the whole thing in a weekend and had a pretty good idea about pointers and stuff afterwards. I feel a lot of people have trouble with pointers didn't read it.
- stevekemp 7y agoMy programming journey went roughly: * ZX Spectrum BASIC * Assembly language (Z80) * FORTH * C * .. Learning C when I already knew assembly language made it obvious what pointers were. I suspect a programmer these days might start with javascript then jump to C and be a little mystified.
- SomeOldThrow 7y agoC is great for some things, but not at others. For instance, the same simplicity you laud makes it very difficult to work with strings or serialization—both are highly manual operations. So—I agree generally with your sentiment, but it's very far from a perfect language. If you're working with word-sized integers it's pretty damn good. Also, ironically, I feel like C presents an excellent case for an evolved language, not a designed language. Its very name is derived from BCPL, as are many of the semantics and notation.
- kps 7y agoK&R C didn't have ‘undefined behaviour’, and I've become convinced that the original ANSI committee didn't intend to create the monster they did. The reason is that Dennis Ritchie wrote a submission to the committee¹ that described the ‘noalias’ proposal as “a license for the compiler to undertake aggressive optimizations that are completely legal by the committee's rules, but make hash of apparently safe programs”, and, that “[i]t negates every brave promise X3J11 ever made about codifying existing practices, preserving the existing body of code, and keeping (dare I say it?) ‘the spirit of C.’” Those comments describe what ‘undefined behaviour’ turned in to. The only reason dmr and others didn't make the same objections to it is that nobody realized at the time what the committee wording implied. ¹ available here: https://www.lysator.liu.se/c/dmr-on-noalias.html https://www.lysator.liu.se/c/dmr-on-noalias.html
- pjmlp 7y agoYes and I wasn't that impressed, given that I already had a experience with several other languages, including for doing low level stuff. What impresses me is reading Burroughs manuals, or the manuals, books and research papers from Xerox PARC and IBM in the 70's.
- 50 7y agoTo piggyback this comment, does anyone know of any co's building something interesting mainly w/ the C programming language (and maybe even w/ Rust)? Also, that are usually open to interns/entry level programmers?
- borgel 7y agoIt's fairly common for folks doing embedded work. What are you interested in?
- 50 7y agoAt the moment, I don't know. Do you any resources where one maybe may possible find something one would be interested in, in the C programming language domain? I've not thoroughly looked into compilers (i.e. LVMM) and operating systems but IIRC, they both went over my head.
- gerbilly 7y agoI don't know about companies, but the linux kernels is C, git is written in C.
- didibus 7y agoHum... Sow why did you stop programming in C?