News for hackers. Stuff that matters.
Re:Let's write a setjmp by flohofwoe on Sunday February 12, 2023 @06:16AM (#34761951)
It's entirely valid C and (assuming this and that are byte pointers) copies a range of bytes until (and including) a zero byte is reached.

With a suffficient warning level (e.g. -Wall on gcc, which should always be enabled anyway, together with -Wextra), compilers will complain about the '=' and ask you to add a pair of braces to make clear that this is actually intended:

    while( (*this++ = *that++) );
It's also one of those cases where the C code matches the output assembly pretty well:

https://www.godbolt.org/z/nz1jbz4Er

As far as "obfuscated C" goes, this is a very tame example though, it's just a straightforward usage of language features, which might look strange only when coming from other languages that don't have pointers or a post-increment operator).

Re:Let's write a setjmp by gpderetta on Sunday February 12, 2023 @06:40AM (#34762068)
> the output assembly pretty well

Ironically, the compiler os likely to recognize this as a strcpy and replace it with a possibly vectorized implementation.

Re:Let's write a setjmp by flohofwoe on Sunday February 12, 2023 @06:51AM (#34762141)
I actually tried to make that happen, but was unsuccessful on GCC and Clang (I've seen this in the past for mempcy() though).
Re:Let's write a setjmp by ckastner on Sunday February 12, 2023 @06:35AM (#34762042)
Doesn't that kind of prove my point?

The code as written was described as beautiful, yet would not have passed -Wall.

It's those little things that can easily get you in C, and there are so many little things to consider.

Re:Let's write a setjmp by flohofwoe on Sunday February 12, 2023 @06:37AM (#34762058)
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 '==').

Re:Let's write a setjmp by ckastner on Sunday February 12, 2023 @06:47AM (#34762116)
I 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.
Re:Let's write a setjmp by flohofwoe on Sunday February 12, 2023 @06:54AM (#34762160)
I'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.

Re:Let's write a setjmp by layer8 on Sunday February 12, 2023 @12:03PM (#34764460)
I 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.
Re:Let's write a setjmp by bee_rider on Sunday February 12, 2023 @12:55PM (#34765002)
I 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.

Re:Let's write a setjmp by layer8 on Sunday February 12, 2023 @01:09PM (#34765131)
In Pascal, you could do

    repeat
        ...
    until c = 0;
which might be even clearer for this use case.
Re:Let's write a setjmp by flohofwoe on Monday February 13, 2023 @05:53AM (#34772110)
I was considering that but had my doubts that people who already find post-increment confusing could handle a do-while loop ;)
Re:Let's write a setjmp by kaashif on Sunday February 12, 2023 @07:19PM (#34768645)
I 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.

Re:Let's write a setjmp by flohofwoe on Monday February 13, 2023 @06:07AM (#34772200)
That'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?

Re:Let's write a setjmp by mjburgess on Sunday February 12, 2023 @06:44AM (#34762095)
`this` and `that` are arrows which range over a stream of data; `=` is copy, and `++` moves the arrow along the stream.

This isn't a "clever one-liner" it is a clear and precise syntax for expressing the operation the machine actually performs.

while(copy(current(stream_a), current(stream_b)) and not end_of_stream(stream_a))

You might prefer the above, but then, that's every other major language. The beauty of C is that the above code has to compile to something like the C version. C just allows you to actually express it

Re:Let's write a setjmp by umanwizard on Sunday February 12, 2023 @10:25AM (#34763496)
> it is a clear and precise syntax for expressing the operation the machine actually performs.

No it’s not. Your compiler will almost certainly translate this into vector instructions, at least.

Re:Let's write a setjmp by umanwizard on Sunday February 12, 2023 @03:18PM (#34766446)
For posterity, I was apparently wrong. It doesn’t autovectorize, with gcc 12.2 -O3 on godbolt, at least.
Re:Let's write a setjmp by mypalmike on Sunday February 12, 2023 @03:30PM (#34766567)
C lacks the expression of many useful common CPU capabilities. Integer rotation and overflow checking come to mind immediately.
Re:Let's write a setjmp by kevin_thibedeau on Sunday February 12, 2023 @01:54PM (#34765637)
GCC warnings can be overly pedantic. It's setup to warn about common footguns but doesn't know what your intent is. In this case it's a common enough idiom to assign within a control statement that GCC has the extra parens escape hatch.

You shouldn't just blindly let your tooling dictate how you work. It's a tool that's supposed to work for you, not control you. -Wall and -Wextra are good baselines but I always disable some of their warnings because I don't need the hassle on known good code.

Re:Let's write a setjmp by jlg23 on Sunday February 12, 2023 @02:47PM (#34766162)
Yes, with -Wall it triggers a warning, but the warning is a false positive because assignment is indeed the intention.