3 ms·
> Also I find counted strings preferable for most tasks, but nul-terminated have the advantage of working so nicely with the ptr++ operation. Is this: whi
by groovy2shoes 10y ago
> Also I find counted strings preferable for most tasks, but nul-terminated have the advantage of working so nicely with the ptr++ operation.
Is this:
while (foo != '\0') {
*bar++ = *foo++;
}
really that much nicer than this:
while (i != len) {
bar[i++] = foo[i++];
}
?
Or even this:
for (; i != len; i++) {
bar[i] = foo[i];
}
?
Don't do this, though:
while (i != len) {
bar[i] = foo[i++];
}
(that's the road to undefined behavior... better watch out for them sequence points!)
> There was real insight behind C's minimalistic string handling.
There really wasn't, though. The simplicity of C's string handling is deceptive. It's full of nuances and inadequacies when used the way the Good Book* describes, and that's the way it's usually used. You're really better off rolling your own string abstraction, or using some library such as bstrings, or even compiling as C++ and using std::string instead (if your C happens to otherwise compile as C++, that is).
* K&R
- Someone 10y ago"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.
- groovy2shoes 10y 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).
- Someone 10y ago"The pointer version still has to test for the nul character anyway, right?" Some architectures set the zero flag on memory loads. I think the PDP is one of them. Google gives me https://groups.google.com/forum/m/#!topic/net.lang.c/LKAYbzXMDew https://groups.google.com/forum/m/#!topic/net.lang.c/LKAYbzX..., which claims that while (*ra++ = *rb++); compiles to L16: movb (r10)+,(r11)+ jeql L17 jbr L16 L17: If you do i != len, you need an extra comparison instruction.
- groovy2shoes 10y agoAh! Interesting. Thank you :)