'I like C, but I have to admit that, sometimes, “The Old Man of Programming” can be a bit of a killjoy. This is one of the most exciting eras in computer history, but lately, C’s acting like he doesn’t even want to have a good time. While the cool kids like Ruby and Haskell are living it up, C’s over in the corner obsessing over bits and bytes and memory alignment and pointers and the stack and machine architecture and unreachable allocations and multiple indirections…and it’s…kind of a buzzkill. You want to tell him, “Dude! Lighten up! This is supposed to be fun!”
But of course C can’t relax. He’s holding the entire computing universe on his shoulders, after all. It’s not turtles all the way down — it’s turtles all the way down, __then C__. Not a lot of room for fun underneath that, is there?
Is there?
Well. Here’s the secret: C does let loose sometimes. And after being bottled up for so long, when the release finally does come, it’s pretty much an F5 of crazy.'
I've programmed in C a fair amount, but I am incapable of understanding the construct contained therein. Specifically, the interaction of the switch and the loop and all those fall-through cases. I would absolutely love it if some C-guru hn-er could describe it in layman's terms?
It's really less complex than it appears, especially once you grok that switch/case is just a computed goto; cases are just labels.
So, the idea behind Duff's Device is just to unroll a loop, dealing in an elegant (some would say abhorrent - they're wrong) way with the "leftover" portion.
So, the canonical Duff's is copying shorts, with the copy loop unrolled to eight copy statements inside the loop. If you want to copy, say 47 shorts, the loop would need to iterate five times, and there would be seven shorts left to copy.
Duff's uses the switch to jump into the middle of the loop just far enough to copy those seven leftover shorts (47 % 8 = 7). The do-while then proceeds to run through the five full iterations.
Modern compilers will do that for you now, though there are still applications for similar code.
Okay, this definitely helps but I'm still struggling (sorry), I'm probably focusing too much on minutiae but:
* At the static level, what does it mean to start the loop at `case 0` then fall through to the termination of the loop? Part of me is surpisued that it even compiles (again, sorry); it's like the mechancis of the loop itself become dependent on the runtime input, at which point my brain begins to frazzle gently.
* Why is the `to` pointer never incremented? Is that some super-clever thing that I'm not seeing or is it just left out of the algorithm for clarity?
- case 0 is first, because this indicates that the modulo operation in the switch statement (count % 8) has no remainder, i.e., all 8 copy instructions should be executed. So, this is first because of the properties of the modulo operation.
The basic idea is that the switch jumps into the body of the loop somewhere, after that it can do blocks of the same function over and over without having to do the conditional check to exit the loop as often.
For example, if you're copying memory, and you want to copy say, 9 bytes then you'd jump into the loop, copy 1 byte, run the conditional check, realize that you're not done, and then copy 8 more bytes, run the conditional check, realize you're done and exit the loop. For the 8*n times you run through the "unrolled" loop after that first pass through, there are a lot less conditional branches, so many processors can execute those instructions faster. That's the idea, anyway.
That is a really good description (and I love the `crappy flowchart`, thanks). But I think what I'm mostly taking away from this is that my brain struggles with the more serious aspects of C-style imperative programming.
It's really just sort of a weird optimization trick. You shouldn't use it in a regular program unless you have a very, very good reason. The fact that it works at all (ie, that you can inject the start of a loop into the middle of a switch statement) is surprising to most people. I've shown this to people who've been programming since before I was born, and they struggled to understand it at first since they had no idea that it was syntactically possible to do that -- it's not the kind of thing you normally think of when writing a program in C. If you know an assembly language and how C maps onto assembly, it's pretty easy to make sense of though, after you get over the shock of the syntax permitting this particular construction.
The other two comments are right, but the context you might be missing is why you would unroll a loop. Due to cache behavior (and other low-level details), doing something eight times and then checking if it needs to be done another eight times has less overhead than checking after each loop iteration. Why eight? It was probably a sweet spot in time vs. code size, at some point. (Processor caches are larger now.)
Duff's device just gets the (remainder of N/8) steps out of the way the first time through, then drops down to looping eight at a time. If it seems more complicated than that, you're probably overthinking it. It's "just" a creative abuse of C syntax, a bunch of offsets and gotos.
Sometimes low-level optimization like this makes a huge difference, but make sure it's a hotspot first, and that the compiler isn't already doing those things for you. Measurements will keep you objective.
Also, if you're doing a lot with C, check out Lua!
Thanks. Lua is on "my list" actually, Fortunately I am only forced to work in C for one particular project (sorry if that sounds negative, C-heads, I'm just a messy enough person to require garbage collection to stop me from messing up too bad).
I've been waiting for something to implement at least something DDD has done for years... and less fugly is nice. Any idea how it handles circular references?
What would be interesting is if someone made a web-based GUI wrapper around such apps. I am sure it would be possible, considering that curses-based wrappers have been around: http://zemljanka.sourceforge.net/cursed/.
It's just that you write it once and it can run anywhere without "installing" many dependencies other than a browser. No fugly GUIs, no inconsistencies, etc.
By web-based I didn't mean it to be on the Internet.
Absolutely — you just open a high port on localhost and open the URL in a browser. I've used this technique before on consulting projects with great success.
I've actually thought about making something like this.
My reasons: collaborative coding + debugging, and IDEs without needing an environment aside from your browser (coding + compiling + debugging code on the device it's made for).
There's a commercial extension of Seaside, where they've put all of the Smalltalk development tools and made AJAX webapps out of them. Basically, you can set things up then do everything through the browser. (Webvelocity)
Whoah, how have I missed ddd completely! I'll definitely give it a try soon. Anyway, I don't know any details about Tenacious C, they are just launching in December.
What a joke. Things like this – and the rhetoric on his site – make systems programming look like more of a dark art than it actually is.
If you're a programmer, should know how your computer works; if pointers are too "hard" for you, you're in the wrong business. You're settling for mediocrity and belittling your own intelligence by assuming you're not capable of tackling this stuff the same way everyone else has.
I also have a lot of respect for people who are willing to teach. But I don't respect teachers that speak of these concepts like they're magic that no mere mortal can understand. This is stuff that everyone can know -- and should know -- and needs to be treated like learning arithmetic, not tensor calculus.
How many programmers today do not know what what a pointer is, or even if they do, how to use/understand them? I'm sure the number is growing, considering the prevalence of languages where pointers aren't even a consideration.
Now if you don't like the features of this IDE, that's fair. You're free to stick to whatever you're currently using. Given that Tenacious C will be a paid app when it is done, I doubt I'll really be interested, given what I can use for free that gets the job done more than adequately.
Gah, I can't remember the details now, but I'm sure one of the interviewees in Coders At Work talks about this point. Something about how the notion of pointers/references is fundamentally wrong because it doesn't reflect our understanding of objects in RL.
I realise I'm being tangential now, but thought I'd mention it anyway.
My thoughts exactly. Pointers are one of the easier "computer science concepts". Instead of storing the entire value right here, we just store where in memory that is. That's all. The side-effects are also relatively simple. Since we're just passing around memory addresses, anything (including called functions) can modify it, since they just write to that memory.
If you can't understand that, I don't see how you are going to write a computer program. The deeper issues are things like object lifetimes, call-by-value versus call-by-reference semantics, and so on.
Neat, but I question the Windows only choice here. A lot of C programmers are developing on a *nix platform. But I see this as being more useful for students learning C and memory management. It's a neat project and might recommend it to students but I'll stick to vim, myself.
Of course, if you learned assembly first instead of Java or somesuch, pointers make 100% intuitive sense, and if you didn't grok them completely you wouldn't have been able to write your first program.
'I like C, but I have to admit that, sometimes, “The Old Man of Programming” can be a bit of a killjoy. This is one of the most exciting eras in computer history, but lately, C’s acting like he doesn’t even want to have a good time. While the cool kids like Ruby and Haskell are living it up, C’s over in the corner obsessing over bits and bytes and memory alignment and pointers and the stack and machine architecture and unreachable allocations and multiple indirections…and it’s…kind of a buzzkill. You want to tell him, “Dude! Lighten up! This is supposed to be fun!”
But of course C can’t relax. He’s holding the entire computing universe on his shoulders, after all. It’s not turtles all the way down — it’s turtles all the way down, __then C__. Not a lot of room for fun underneath that, is there?
Is there?
Well. Here’s the secret: C does let loose sometimes. And after being bottled up for so long, when the release finally does come, it’s pretty much an F5 of crazy.'