1

Program file name - armstrong3.c.

#include <stdio.h>
#include <math.h>

int main(void) {
int i, sum, num, rem,x;
x=pow(2,5);
printf("%d\n", x);
printf("List of 3 digit armstrong numbers \n");
for (i=100; i<=999; i++) {
    num=i;
    sum=0;
    while (num>0) {
        rem=num%10;
        sum=sum+pow(rem,3);
        num/=10;
    }
    if (i==sum) 
        printf("%d\n", i);  
    }
return 0;
}

This simple program finds 3 digit armstrong numbers. To calculate the cube I am using pow() of math.h. It didn't work initially and gave the famous error during compilation:

armstrong3.c:(.text+0x91): undefined reference to `pow' collect2:

error: ld returned 1 exit status.

Then I compiled it with gcc armstrong.c -lm, and it worked fine.

Then I used another pow() function in the second line of the main() function and commented out the earlier pow() function which I was using to calculate the cube. Strangely, the program compiled fine with gcc armstrong3.c.

The program posted by me gets compiles fine using gcc armstrong.c -lm.

The following scenario is my current issue:

With the second pow() commented out it gcc armstrong.c compiles with no warnings and errors. No -lm flag required.

If I uncomment the second pow() function in the program, it does not compile and gives the above mentioned error. And with -lm it works fine.

Why is there this unusual behavior with the same function in two places inside the same program?

Compiler: gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04).

Community
  • 1
  • 1
amritesh
  • 83
  • 6
  • See [log(10.0) can compile but log(0.0) cannot?](http://stackoverflow.com/q/24294578/1708801) basically gcc can optimize away calls to certain builtins when using constant expression arguments. Try using `-fno-builtin` – Shafik Yaghmour Oct 02 '15 at 09:33

2 Answers2

4

Then I used another pow() function in the second line of the main() function and commented out the earlier pow() function which I was using to calculate the cube. Strangely, the program compiled fine with gcc armstrong3.c.

pow is an intrinsic function. When you specify all its arguments as compile time constants, as in pow(2, 5), the compiler replaces the call with its value.

That only happens for integer arguments. Because when you pass floating point arguments the result of pow depends on the current floating point rounding mode, which is not known at compile time.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
1

This behavior is caused by inlining the pow function result in case of constant expressions in its call.

Juraj Blaho
  • 13,301
  • 7
  • 50
  • 96
  • Is there a reference link documenting this behavior of `gcc`? – rootkea Oct 02 '15 at 08:12
  • @rootkea: I don't know about such reference, but it should be easy to confirm that by inspecting the generated code. – Juraj Blaho Oct 02 '15 at 08:13
  • @rootkea You don't need a special documentation for this. The compiler knows how this function works (because it's a standard C function) and it has every right to replace the call with a better equivalent, a constant in this case. – Alexey Frunze Oct 02 '15 at 08:34