5 ms·
That extra pair of braces doesn't make the code 'ugly' ;) And the code without braces is still entirely valid standard C, the warning is essentially just a lin
by flohofwoe 4y ago
That extra pair of braces doesn't make the code 'ugly' ;)
And the code without braces is still entirely valid standard C, the warning is essentially just a lint to protect against typos (similar to JS linters warning about '===' vs '==').
PS: let's see if the alternatives would be any more readable:
char c;
while (c = *that++) {
*this++ = c;
}
...this is already buggy because it doesn't copy the final zero byte, so the test must happen inside the loop body and also lets try to get rid of the post-increment:
while (true) {
char c = *that;
*this = c;
this += 1;
that += 1;
if (c == 0) {
break;
}
}
...hmm not really any more readable...
Let's try with an index...
while (true) {
char c = that[i];
this[i] = c;
i += 1;
if (c == 0) {
break;
}
}
...might be a bit easier to grasp when used to other languages, but readability hasn't improved all that much I'd say...
For reference, MUSL also just uses the original approach:
https://github.com/esmil/musl/blob/master/src/string/strcpy.c https://github.com/esmil/musl/blob/master/src/string/strcpy....
- ckastner 4y agoI was unclear, sorry: I didn't mean to say that the extra braces make it uglier, I meant to point out that something that was described as beautiful was actually flawed. The flaw was minor in this case because the identifier names and lack of body make the intention clear, but my point is that there are a lot of minor things in C that can come and bite you at any time. Edit: You are right, I don't see a way this could have been implemented more readable without sacrificing some performance. First thing I thought of was: void cp(const char* from, char* to) { while (*from) { *to = *from; to++; from++; } } But that does not reduce to the original case.
- flohofwoe 4y agoI've added a couple of examples trying to find a more readable version, which actually isn't trivial. Sorry for the 'post-edit' :) As for performance: I don't think such details matter much, first, compilers are pretty good to turn "readable but inefficient" code into the same optimal output (aka "zero cost abstraction"). And a really performance-oriented strcpy() wouldn't simply copy byte by byte anyway, but try to move data in bigger chunks (like 64-bit or even SIMD registers). Whether this is then actually faster also depends on the CPU though.
- layer8 4y agoI would use a do-while, because at least one char is always copied: char c; do { c = *src++; *dst++ = c; } while (c != 0); The post-increment is idiomatic enough in C-based languages that I wouldn’t worry about that.
- bee_rider 4y agoI don’t write much C, but to an outsider like me this is a pretty big improvement. It is a shame post-test loops aren’t more popular, given the similarity to the assembly they output. Seems more mechanically sympathetic. Oh well, at least it is an excuse to whip out the goto.
- layer8 4y agoIn Pascal, you could do repeat ... until c = 0; which might be even clearer for this use case.
- flohofwoe 4y agoI was considering that but had my doubts that people who already find post-increment confusing could handle a do-while loop ;)
- kaashif 4y agoI find it crazy that you improve the readability so much and say readability hasn't improved that much. The order things happen in *this++ is not obvious unless you know a bunch of C-specific rules, while the ordering of multiple statements is obvious even to someone who doesn't know C. Perhaps C programmers should find this obvious, but it seems to me more like cognitive overhead which has a non zero chance of confusing someone at some point.
- flohofwoe 4y agoThat's almost a philosophical question ;) Should code in a specific language be more readable to programmers familiar to that language or to programmers who are not familiar? E.g. I guess for a mathematician, all imperative languages are probably 'weird', while something like Haskell feels more familiar?