4

I tried this code

/*main.c*/
#include <stdio.h>      /* printf */
#include <math.h>       /* sqrt */

int frequency_of_primes (int n) {
  int i, j;
  int freq = n - 1;
  for (i = 2; i <= n; ++i)
  for (j = sqrt(i); j > 1; --j)
    if (i%j==0) {--freq; break;}
  return freq;
}

int main() {
  printf("%f\n", sqrt(4.0));
  return 0;
}

and compiled it with gcc main.c, it reported that undefined reference tosqrt'. I already know add-lm` option can resolve this issue. But what really surprises me is this:

#include <stdio.h>      /* printf */
#include <math.h>       /* sqrt */

// int frequency_of_primes (int n) {
//   int i, j;
//   int freq = n - 1;
//   for (i = 2; i <= n; ++i)
//   for (j = sqrt(i); j > 1; --j)
//     if (i%j==0) {--freq; break;}
//   return freq;
// }

int main() {
  printf("%f\n", sqrt(4.0));
  return 0;
}

The main function also calls sqrt, but ld doesn't report any errors.

TorosFanny
  • 1,702
  • 1
  • 16
  • 25
  • 1
    If you add `-ffast-math`, most compilers will use the appropriate machine instructions instead of a function call, so you don't need libm.... Even for non-constants. – technosaurus Oct 22 '15 at 10:39

1 Answers1

7

That's because the optimizer is handling the constant case you're using.

It's the sqrt(i) call inside frequency_of_primes() that's the problem, the call in main() is optimized out. You can figure that out by reading the generated code for the latter case, it'll just load a constant 2.0 and be done with it.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    Yes, thank you for your answer. Replace sqrt(4.0) with sqrt(i) which double i = 4.0 and compile with gcc -O3 then no error reported, but not when compile without optimizing. – TorosFanny Oct 22 '15 at 11:02