Append -lm to the end of your gcc command.
With all recent versions of GCC on GNU/Linux systems like Ubuntu, when you use the math library, you have to explicitly link to it. It is not automatically linked to along with the rest of the standard C library.
If you are compiling on the command-line with the gcc or g++ command, you would accomplish this by putting -lm at the end of the command.
For example: gcc -o foo foo.c -lm
Append -lm to the end of your gcc command.
With all recent versions of GCC on GNU/Linux systems like Ubuntu, when you use the math library, you have to explicitly link to it. It is not automatically linked to along with the rest of the standard C library.
If you are compiling on the command-line with the gcc or g++ command, you would accomplish this by putting -lm at the end of the command.
For example: gcc -o foo foo.c -lm
If you are going to compile a C program with math.h library in LINUX using GCC or G++ you will have to use –lm option after the compile command.
gcc xyz.c -o xyz -lm
Here,
gcc is compiler command (compiler name)
xyz.c is a source file name.
-o is an option to specify the output file.
xyz is the name of the output file.
-lm is an option to link againt the math library (libm).
for more details here is the link containing complete article on it.
Compiling C program with math.h in Linux.
The problem is coming from the linker, ld, rather than gcc (hence the exit status message). In general ld requires objects and libraries to be specified in the order user supplier, where user is an object that uses a library function and supplier is the object which provides it.
When your test.c is compiled to an object the compiler states that fmod is an undefined reference
$ gcc -c test.c
$ nm test.o
U fmod
0000000000000000 T main
(nm lists all the functions referred to by an object file)
The linker changes the undefined references to defined ones, looking up the references to see if they are supplied in other files.
$ gcc -lm test.o
$ nm a.out
0000000000600e30 d _DYNAMIC
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_
00000000004006a8 R _IO_stdin_used
w _Jv_RegisterClasses
0000000000600e10 d __CTOR_END__
...
0000000000601018 D __dso_handle
w __gmon_start__
...
U __libc_start_main@@GLIBC_2.2.5
0000000000601020 A _edata
0000000000601030 A _end
0000000000400698 T _fini
0000000000400448 T _init
0000000000400490 T _start
00000000004004bc t call_gmon_start
0000000000601020 b completed.7382
0000000000601010 W data_start
0000000000601028 b dtor_idx.7384
U fmod@@GLIBC_2.2.5
0000000000400550 t frame_dummy
0000000000400574 T main
Most of these refer to libc functions that are run before and after main to set the environment up. You can see that fmod now points to glibc, where it will be resolved by the shared library system.
My system is set up to use shared libraries by default. If I instead force static linking I get the order dependency you see
$ gcc -static -lm test.o
test.o: In function `main':
test.c:(.text+0x40): undefined reference to `fmod'
collect2: ld returned 1 exit status
Putting -lm later in the linker command, after test.o, allows it to link successfully.
Checking the symbols fmod should now be resolved to an actual address, and indeed it is
$ gcc -static test.o -lm
$ nm a.out | grep fmod
0000000000400480 T __fmod
0000000000402b80 T __ieee754_fmod
0000000000400480 W fmod
From the gcc(1) manpage: "the placement of the -l option is significant."
Specifically:
-llibrary -l library Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.) It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded. The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name. The directories searched include several standard system directories plus any that you specify with -L. Normally the files found this way are library files---archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with lib and .a and searches several directories.
math.h library doesn't compile on linux (even when compiling with -lm)
Trying to compile a C program with GCC and math.h header - Stack Overflow
How to link math.h using makefile for gcc
Is #include <math.h> necessary?
Videos
I'm studying C programming for an exam at my university, and since we will take the exam on computers using Linux Debian our teachers have told us to install a Debian virtual machine (Oracle VM Virtualbox) to practice.
I use geany to code and I have to use the math.h library sometimes. I know in order to do that i need to compile with gcc -lm but it doesn't seem to work. Can anyone help me?
The command I used on the terminal is:
gcc -lm 2_razzo_parte_opzionale.c
The error that shows up on the shell is:
/usr/bin/ld: /tmp/cceZf8ZJ.o: in function ˋriempi_array': 2_razzo_parte_opzionale.c:(.text+0x2fc): undefined reference to ˋpow'/usr/bin/ld: 2_razzo_parte_opzionale.c:(.text+0x3ee): undefined reference to ˋlog'collect2: error: ld returned 1 exit status
If it is useful in any way, this is the code i wrote:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void ask_parametri(double *m_in, double *tasso_esp, double *vel_esp){
int count=0;
printf("Richiesta dei parametri\n"); printf("\n");
do { if(count!=0){printf("Errore: inserire un valore maggiore di 0\n");}
else{}
printf("Inserire la massa iniziale di carburante (>0) [kg]: ");
scanf("%lf",m_in);
count++;
}while(*m_in<=0);printf("\n"); count=0;
do { if(count!=0){printf("Errore: inserire un valore maggiore di 0\n");}
else{}
printf("Inserire il tasso di espulsione del carburante (>0) [kg/s]: ");
scanf("%lf",tasso_esp);
count++;
}while(*tasso_esp<=0);printf("\n"); count=0;
do { if(count!=0){printf("Errore: inserire un valore maggiore di 0\n");}
else{}
printf("Inserire la velocità di espulsione del carburante (>0) [m/s]: ");
scanf("%lf",vel_esp);
count++;
}while(*vel_esp<=0);printf("\n");
}
void ask_intervallo(double *t_f, double t_max){
int count=0;
do{if(count!=0){printf("Errore: inserire un valore minore di %lf\n",t_max);}
else{}
printf("Inserire la lunghezza dell'intervallo di tempo in esame [s]: ");
scanf("%lf",t_f);
count++;
}while(t_max<=*t_f);printf("\n");
}
int ask_step(){
int n, count=0;
do{ if(count!=0){printf("Errore: inserire un valore maggiore di 0\n");}
else{}
printf("Quanti campionamenti si vogliono? ");
scanf("%d",&n);
count++;
}while(n<=0);printf("\n");
return n;}
void riempi_array(double *t, double *m, double *v, int n, double t_f, double m_0, double m_punto, double w){
int i;
double dt, k=0.5;
t[0]=0;
m[0]=m_0;
v[0]=0;
dt=t_f*(1-k)/(1-pow(k,n));
for(i=1;i<=n;i++){
dt=k*dt;
t[i]=t[i-1]+dt;
m[i]=m_0-m_punto*t[i];
v[i]=-w*log(m[i]/m_0);
}
}
void grafico(char *file, double *t, double *m,double *v,int n){
FILE *fp;
fp=fopen(file,"w");
int i;
for(i=0;i<=n;i++){
fprintf(fp,"%lf %lf %lf\n",t[i],m[i],v[i]);
}
fclose(fp);
}
int main(){
double m0,m_punto,v_esp, t_0, t_max;
int n_step;
double *m_0=&m0, *dm_dt=&m_punto, *w=&v_esp, *t_finale=&t_0;
double *t;
double *m;
double *v;
ask_parametri(m_0,dm_dt,w);
t_max=m0/m_punto;
ask_intervallo(t_finale,t_max);
n_step=ask_step();
t= (double *) calloc(n_step+1,sizeof(double));
m= (double *) calloc(n_step+1,sizeof(double));
v= (double *) calloc(n_step+1,sizeof(double));
riempi_array(t,m,v,n_step,t_0,m0,m_punto,v_esp);
grafico("razzo2.dat",t,m,v,n_step);
return 0;}CC = gcc CFLAGS = -O default: run run: build run < program.cs build: compile $(CC) -o run main.o closed_hashtable.o compile: main.c closed_hashtable.c closed_hashtable.h $(CC) -c main.c $(CC) -c closed_hashtable.c clean: $(RM) *.o *.gch
How do I link math.h using the makefile above?
So I started to study C and noticed something interesting.
TL;DR:
Building the code gives me a warning/error, telling me to declare the function or to include math.h. But I can ignore that message and still run the code and the function gets executed. I build the code by using gcc code_name.c -o code_name or just "run code" with Vs Code's Code Runner. Both will give me the error but running the code with ./code_name works fine, the functions are applied. I can ignore the error message and still run the code. If you use Replit, it works as well, without any messages.
I use VS Code and run my code in two different ways. Either Code-Runner or the Terminal, usually Code-Runner and Terminal when it doesn't work with it.
When running the following code:
#include <stdio.h>
// #include <math.h>
int main(){
printf("%f\n", pow(2,3));
return 0;
}This happens with Code-Runner:
>https://imgur.com/a/YsgSyvq (First Image)
Note that Code-Runner automatically creates the .exe and I can run the code with the terminal (PowerShell) by using
./code_name
>https://imgur.com/a/YsgSyvq (Second Image)
But again, when I try to use
gcc Working_Numbers.c -o WN
to build the code, it sends a warning message, telling me that I must use math.h or declare pow() (the math function).
But I can still do
./WN
And the code runs without issues.
>https://imgur.com/a/YsgSyvq (Third Image)
So does C already have these math functions built into it or is #include <math.h> necessary?