"Is this:
while (foo != '\0') {
bar++ = foo++;
}
really that much nicer than this:
while (i != len) {
bar[i++] = foo[i++];
}"
Not visually, but the latter increments i twice in every loop :-). It also typically uses an extra register and requires an explicit 'compare with zero'. Both mattered more 40+ years ago.
> the latter increments i twice in every loop :-).
D'oh! Good catch. That's what I get for coding without testing at 3am... Just realized `foo != '\0'` should be `* foo != '\0'`, too. Derp.
> It also typically uses an extra register and requires an explicit 'compare with zero'.
Okay, I see the extra register, but I'm lost on any extra comparisons versus the pointer-arithmetic version. The pointer version still has to test for the nul character anyway, right?
> Both mattered more 40+ years ago.
Indeed, but I'm talking about today. We can now afford the safety that comes with using explicit lengths rather than sentinels. (I'm inclined to think Dennis Ritchie could've afforded it, too, considering that Pascal (among others) was using explicit lengths for strings (and indeed all arrays) around the same time C was invented, and did so on similar hardware to boot. Bounds checking is pretty damn cheap, all things considered, even on a PDP-11 (the PDP-10, while not exactly a predecessor to the PDP-11, ran TeX written in WEB / Pascal, and was favored by some Lisp hackers as practically a Lisp machine (in fact, Lisp was the first thing DEC brought up on the PDP-10, or so I'm told...), so I think it could afford bounds checking, at least).
Not visually, but the latter increments i twice in every loop :-). It also typically uses an extra register and requires an explicit 'compare with zero'. Both mattered more 40+ years ago.