Search code examples
csqrt

Why does sqrt function not work for values taken through user input?


The following code:

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

int main(void)
{
    long long int a;
    scanf("%lld", &a);
    printf("%lf", sqrt(a));
    return 0;
}

gives output:

source_file.c: In function ‘main’:
source_file.c:9:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%lld", &a);
     ^
/tmp/ccWNm2Vs.o: In function `main':
source.c:(.text.startup+0x65): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

However, if I do long long int a = 25; and delete the scanf statement, or simply do sqrt(25), both of them work (correctly give output 5.000000).

I checked this question, but it is for C++ and uses function overloading, whereas afaict C does not have function overloading (that's why we have sqrtf, sqrt, sqrtl if I'm not wrong). Moreover, the above code fails whether I take long long int or double type of a. So, the questions are probably not related.
Also, regarding the other linked question, the error did not occur for me for constantly defined values, which instead happens to be the case with the linked question.

What is the reason then? Why would a constant value work for sqrt, while a variable user input value won't?


Solution

  • Like was mentioned in the comments, you haven't linked against libm so sqrt is undefined at link-time.

    Why would a constant value work for sqrt, while a variable user input value won't?

    Because GCC recognizes sqrt as a builtin function and is able to evaluate the square root of a compile-time constant at compilation time, and forgoes the call to sqrt altogether, thus avoiding the subsequent linker error.

    The ISO C90 functions ... sqrt, ... are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function).

    If you were to add -fno-builtin-sqrt, you would see the linker error regardless of what you pass to sqrt.