4

I have two segments of code, both identical except for one line. One program fails to compile, and the other one is successful. I do link the math libraries when I execute cc to compile the code.

I'm using the double sin(double) function. It's apparently defined in math.h, although I looked in /usr/include/math.h and found no reference to the sin() function.

See http://www.gnu.org/software/libc/manual/html_mono/libc.html#Trig-Functions

The sin() function does work in one code segment I give but not in the other.

//Successful program - demo1.c
#include <stdio.h>
#include <math.h>

int main (void)
{
    double input, sine_A; 
    input = 6.2830;
    sine_A = sin(6.2830);
    printf("sine=%f\n",sine_A);
    return 0;
}

This is the failed program:

//Failed program - demo2.c
#include <stdio.h>
#include <math.h>

int main (void)
{
    double input, sine_A;
    input = 6.2830;
    sine_A = sin(input);
    printf("sine=%f\n",sine_A);
    return 0;
}

$ cc -lm demo2.c

/tmp/ccnpIWZd.o: In function `main':
demo2.c:(.text+0x1c): undefined reference to `sin'
collect2: ld returned 1 exit status

This has been leaving me feeling a bit stupid, or at least, feeling I missed something over the years.

Joshua Dwire
  • 5,415
  • 5
  • 29
  • 50
Timothy Legg
  • 41
  • 1
  • 3
  • I believe you are right. I wish I had read this last week. This was what I would have liked to have found. Thank's for sending this my way! – Timothy Legg Oct 04 '13 at 19:02
  • Very similar to [log(10.0) can compile but log(0.0) cannot?](http://stackoverflow.com/q/24294578/1708801) – Shafik Yaghmour Jan 09 '15 at 20:00
  • @KeithThompson please see [Is this conflict of interest an abuse of closing privileges?](http://meta.stackoverflow.com/q/277126/1708801) I pretty much avoid closing question as duplicates of questions I have an answer on since I agree with George this seems like a conflict of interest. As I commented to him it seems like in these cases the dup hammer should change to a regular non-binding vote. In cases were someone else does not find a better duplicate the advice seems to be flag it or post on meta. – Shafik Yaghmour Jan 09 '15 at 21:45
  • @ShafikYaghmour: I don't agree that it's a conflict of interest, though I suppose I can see how it might appear that way. In my opinion, this question is clearly a duplicate of the other one (and probably of a number of others). I think there was a comment referring to the other question (which apparently was later deleted). I didn't even remember that I had posted an answer, though I was aware of it before I cast my vote. It had also slipped my mind that I can close a C question as a duplicate with a single vote. Do you disagree that this is a duplicate of that question? – Keith Thompson Jan 09 '15 at 22:03
  • @ShafikYaghmour: Also, I wouldn't mind having an option either to close a question by myself *or* to cast an ordinary close vote, but that mechanism doesn't exist. – Keith Thompson Jan 09 '15 at 22:04

2 Answers2

2

You are not linking with the math library. If you are using gcc you need to pass -lm at the end.

So why is the first example working ? I can speculate that's happening because you are calling sin directly on a double literal and gcc can do its own magic without requiring libm - it can simply compute it directly and replace the call entirely with the result.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • I tried `gcc -lm a.c` without any problem. – CS Pei Oct 04 '13 at 18:55
  • 1
    It is interesting, I just noticed that if I exclude the "-lm" as a parameter of cc, the outcome is exactly the same. The failed one still fails and the successful one still compiles. – Timothy Legg Oct 04 '13 at 18:56
  • @TimothyLegg are you putting `-lm` **at the end** ? – cnicutar Oct 04 '13 at 18:57
  • I moved it to the end, and both compile properly. Thanks for solving this. I swear that I used to pass "-lm" before INFILE in the past; could this have changed? This usage works, but contradicts the man page for cc. – Timothy Legg Oct 04 '13 at 19:00
  • @TimothyLegg There's a [C FAQ](http://c-faq.com/fp/libm.html). – cnicutar Oct 04 '13 at 19:01
1

-lm needs to be at the end of the command, most likely in the first case with the literal the compiler is optimizing out the call to sin and therefore does not need to link against the library. This is called constant folding and for example we can see in the gcc docs on Other Built-in Functions Provided by GCC says(emphasis mine):

GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with __builtin_ are always treated as having the same meaning as the C library function even if you specify the -fno-builtin option. (see C Dialect Options) Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function is emitted.

Here is a live demo which we can see from the assembly in the literal case gcc optimizes out the call to sin and this demo shows the non-literal case and we see in the assembly:

call    sin
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • 1
    Just curious, how is the first one optimized out? I see it uses a constant and the second uses a variable, but how did you make that leap? – KevinDTimm Oct 04 '13 at 18:57
  • @cnicutar says - `calling sin directly on a double literal and gcc can do its own magic without requiring libm`, I think that might be the answer, you just got there empirically :) – KevinDTimm Oct 04 '13 at 18:59
  • 1
    @KevinDTimm I think we are saying the same thing – Shafik Yaghmour Oct 04 '13 at 18:59