1. 19
  1.  

  2. 5

    That was a sneaky trick. It wasn’t really about C but about a particular C ABI on a particular archiecture.

    1. 3

      Ooooo.

      Evil. Very very evil.

      1. 1

        Can anyone explain how the very last example works?

        double NoOp(double a) {
            return a;
        }
        
        int main() {
            double (*ReturnLastReturnValue)() = (double (*)())&NoOp;
            double value = pow(0.99, 100.0);
            double other_value = ReturnLastReturnValue();
            printf("Value: %lf   Other value: %lf\n" value, other_value);
        }
        
        1. 5

          I didn’t read the full article, but I read enough to get the gist. I imagine that (in at least some calling conventions) the register via which the first double argument is passed into the function is also the same register to which the returned double would subsequently be written. By casting the function to a function type with no arguments, in all likelihood the compiler will generate program text that does nothing to the double-shaped register in question. Calling it immediately after a function that stored a return value in that same double register means that you’ll have basically done “nothing” and will re-read the (untouched) register to get the same return value.