They don't "accomplish the same thing". They accomplish complementary parts of the same thing. Typically you have to do both: doing just one, or just the other, is totally insufficient.
Here's an imperfect analogy: Suppose you want an addition on your house. At the start of the project, you sign your name on a contract with the builder, specifying the size and finish of the addition. At the end of the project, you sign your name on a check to pay the builder for his work. What's the difference between signing the contract and signing the check? Why do you have to do both, if they both do the same thing, namely getting you your new addition?
Including a header is (sort of) like signing a contract. When you say #include <math.h>
, you're saying "Hey, compiler, there are some math functions. Like sqrt()
, which accepts a double
and returns a double
. So if I write int x = sqrt(144)
, make sure you do a conversion from int
to double
before passing the number to sqrt
, and make sure you do a conversion from double
back to int
before assigning the result to x
."
Linking against a library is (sort of) like paying your bill. (Actually, if I'm honest, it's almost nothing like paying a bill, but bear with me.) When you put -lm
at the end of the command line, you're saying "Hey, compiler, those math functions we agreed on, the ones whose details are specified in the contract called <math.h>
, the ones I've been calling, now I'm paying up, here's where those functions actually are."
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…