2

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?

Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84

2 Answers2

5

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.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
1

Functions inside the stdlib.h and stdio.h have implementations in libc.so (or libc.a for static linking), which is linked into executable by default (as if -lc were specified).

GCC can be instructed to avoid this automatic link with the -nostdlib or -nodefaultlibs options.

Functions in math.h have implementations in libm.so (or libm.a for static linking), and libm is not linked in by default.

Basically, C++ runtime libstdc++ requires libm, so if you compile a C++ program with GCC (g++), you will automatically get libm linked in.