Why do you have to link the math library in C?
The functions in stdlib.h
and stdio.h
have implementations in libc.so
(or libc.a
for static linking), which is linked into your executable by default (as if -lc
were specified). GCC can be instructed to avoid this automatic link with the -nostdlib
or -nodefaultlibs
options.
The math functions in math.h
have implementations in libm.so
(or libm.a
for static linking), and libm
is not linked in by default. There are historical reasons for this libm
/libc
split, none of them very convincing.
Interestingly, the C++ runtime libstdc++
requires libm
, so if you compile a C++ program with GCC (g++
), you will automatically get libm
linked in.
How to link to the C math library with CMake?
Many mathematical functions (pow
, sqrt
, fabs
, log
etc.) are declared in math.h
and require the library libm
to be linked. Unlike libc
, which is automatically linked, libm
is a separate library and often requires explicit linkage. The linker presumes all libraries to begin with lib
, so to link to libm
you link to m
.
You have to use it like target_link_libraries(ch4 m)
to link libm
to your target. The first argument must be a target. Thus it must be used after add_executable(ch4 ch4.c)
like:
add_executable(ch4 ch4.c)
target_link_libraries(ch4 m)
Linking files/headers in C
- Yes, though going through assembly is an extra step (you can just compile the C source to an object). Internally, the compiler will have many more stages: parsing code into an AST, generating intermediate code (e.g. LLVM bitcode for
clang
), optimizing, etc. math.h
just defines protypes for the standard math librarylibm.a
(which you link with-lm
). The functions themselves live in object files archived insidelibm.a
(see below).- Static libraries are just archives of object files. The linker will check what symbols are used and will extract and link the object files that export those symbols. Those libraries can be manipulated with
ar
(for examplear -t
lists the object files in a library). Dynamic (or shared) libraries are not included in the output binary. Instead, the symbols your code needs are loaded at runtime. You would simply create an header file with your
extern
ed prototypes:#ifndef MYLIB_H
#define MYLIB_H
extern int mylib_something(char *foo, int baz);
#endifand ship it with your library. Of course the developer must also link (dinamically) against your library.
The advantage of static libraries is reliability: there will be no surprises, because you already linked your code against the exact version you're sure it works with. Other cases where it may be useful is when you're using uncommon or bleeding-edge libraries and you don't want to install them as shared. This comes at the cost of increased binary size.
Shared libraries produce smaller binaries (because the library is not in the binary) with smaller RAM footprint (because the OS can load the library once and share it among many processes), but they require a bit more care to make sure you're loading exactly what you want (e.g. see DLL Hell on Windows).
As @iharob notes, their advantages don't just stop at binary size. For example, if a bug is fixed in a shared library all programs will benefit from it (as long as it doesn't break compatibility). Also, shared libraries provide abstraction between the external interface and the implementation. For example, say an OS provides a library for applications to interface to it. With updates, the OS interface changes, and the library implementation tracks those changes. If it was compiled as a static library, all programs would have to be recompiled with the new version. If it was a shared library, they wouldn't even notice it (as long as the external interface stays the same). Another example are Linux libraries that wrap system/distro-specific aspects to a common interface.
Undefined references for mat.h in C
You need to append -lmx
or add -lC:\Path\to\libmx.dll
in your gcc command. you may also need -lmex -lm
Related Topics
While (1) VS. for (;;) Is There a Speed Difference
Make Shared_Ptr Not Use Delete
Correct Use of Std::Cout.Precision() - Not Printing Trailing Zeros
Unnecessary Curly Braces in C++
What Is Shared_Ptr's Aliasing Constructor For
Why Can't You Use Offsetof on Non-Pod Structures in C++
Is Auto as a Parameter in a Regular Function a Gcc 4.9 Extension
How to Write Custom Input Stream in C++
How to Measure CPU Time of a Specific Set of Threads
Selecting a Member Function Using Different Enable_If Conditions
Regex Replace with Callback in C++11
Redirecting Cout to a Console in Windows
Difference Between Pointer and Reference as Thread Parameter
How to Input Variables Using Cin Without Creating a New Line