5 ms·
The thing I love about C is it almost always does what you want fast, but you are never certain. No matter how much you think you know C, there is always some n
by danieltillett 9y ago
The thing I love about C is it almost always does what you want fast, but you are never certain. No matter how much you think you know C, there is always some new edge case to experience. C is exciting.
- akvadrako 9y agoI completely disagree with this. C is the only language I ever used I felt I had mastered. Sometimes I needed to check things in the spec or pause to consider the C99/C89 discrepancies, but essentially I knew everything about it after just a few years of daily use. I've never felt that way with Python, JS, Ruby, Java, C++ or any of the other languages I've used. They are at least 10X more complex in terms of primitives and non-trivial interactions.
- barrkel 9y agoC is deceptive, though. It encourages a mental model of high-level assembler, but it's an assembler for an abstract machine, not the actual machine; and compilers are increasingly making the difference evident.
- akvadrako 9y agoMaybe many people do have incorrect assumptions about C, but I wouldn't say it's deceptive. The abstract nature becomes plain when using an optimising compiler for a while. And they have been the norm for at least 20 years.
- mrec 9y agoOptimizing compilers have been around for yonks, sure, but I think taking aggressive advantage of UB is relatively recent. See e.g. Regehr in 2012 [1] : > The current crop of C and C++ compilers will exploit undefined behaviors to generate efficient code [...], but not consistently or well. It’s time for us to take this seriously. [1] https://blog.regehr.org/archives/761 https://blog.regehr.org/archives/761
- akvadrako 9y agoI see your comment is grey, so I guess people down-voted you and maybe you want to know why. It's because you are wrong. Compiler optimisations have always been relevant; even in the 90's they would omit entire blocks of code or reorder operations for example. I assume now it's more aggressive, because undefined behavior should never be relied upon. That's the point.
- mrec 9y agoI think you're reading me as saying something much stronger than what I actually meant. When we talk about C being "deceptive" we don't need to consider optimizations that respect the as-if rule. (Well, maybe when looking at the C->asm mapping or trying to benchmark, but that's not the level most people are working at.) The trend toward UB-based optimizations seems significant to me because they can and will take a bunch of C code which looks superficially reasonable, and which used to do X as intended, and suddenly (and perfectly legally) make it start doing Y instead. I assumed that's what barrkel was alluding to above. And yes, I'm sure there are old optimizations which will also do that, but basic things like hoisting and reordering and unrolling and dead-code elimination don't fall into that category.
- akvadrako 9y ago> And yes, I'm sure there are old optimizations which will also do that So then it's not new behavior.
- sevensor 9y agoI think the pre- versus post-increment is a great example of this -- Assembly language is unambiguous about when the increment happens. It happens when you hit the increment instruction. The situation in C is almost intentionally confusing. This was done back in the early days of structured programming. I suspect the motivation was to win people over from using gotos for everything, since it allows for variation in how loops and conditionals are executed.
- pkaye 9y agoSome of the processors back then had various pre-increment vs post-decrement addressing modes so there was a performance difference which one you used. To keeps things unambiguous, use the increment operator in a statement by itself.
- sevensor 9y agoInteresting, that sheds some light on the situation! And indeed, I do always use the increment operator by itself. The amount of extra thought it takes to distinguish while(i--) from while(--i) just isn't worth it, when instead I could write for(;i>0;i--) which is very clear about what the last value of i in the loop is.
- kahlonel 9y agoLookup "Dunning-Kruger effect"
- danieltillett 9y agoThat is where the excitement comes from. You think you know C, but when you least expect it something come up that bites you in the backside. I love C for its warts and all, but you should treat it like a tamed wild animal.
- empath75 9y agoAnd always new buffer-overflows to find.
- Analemma_ 9y agoI know, right? The GP’s point baffles me. C is a tool. I don’t want my tools to be exciting! I want my movies and vacations and relationships to be exciting, but not my tools. I want my tools to be boring and predictable.
- megous 9y agoI don't find it a common bug in day to day programming. It may be well known because of the security implications. I get perhaps a 2-3 crashes a year from buffer overflow when developing an app. OTOH, I'm constantly being pumelled by failed type checks, undefined variables, uninitialized variables, etc. Last time compiler even warned me about buffer overflow, which was nice.
- reza_n 9y agoDo you have any examples of this uncertainty? I hear this argument a lot, but have a hard time understanding why this seems to be a common grievance. I've been writing C for years and never once did I hit a scenario of dealing with undefined or uncertain behavior. Writing normal C is very well defined. No?
- pacaro 9y agoI find this hard to believe. Even initialized variables are undefined behavior, I’ve yet to meet a c programmer that hasn’t been bitten by this.
- reza_n 9y agoPlease explain how that is UB?
- pacaro 9y agoUgh. Sorry autocorrect, should read “uninitialized variables”
- reza_n 9y agoIt is well understood that all variables need to be initialized. Most compilers consider uninitialized variables an error. So I would say someone running into this and possibly other UB scenarios is just a case of writing bad code.
- dxhdr 9y agoC is very unexciting to me, in a good way. With C you can figure out what the compiler has done by inspecting the generated code. Have fun doing that with an interpreted language, or compiled output from any other language for that matter! Actually there are a few other languages that are great for debugging runtime code behavior; Lua comes to mind.