I have written a simple program fabs.c
to display the absolute value of a floating point number.
#include <stdio.h>
#include <math.h>
int main(void)
{
float f;
printf("Enter a floating-point number: ");
scanf("%f", &f);
printf("Its absolute value is %f.\n", fabs(f));
return 0;
}
fabs() function requires including the math.h
header file, but I compiled successfully without -lm
option.
gcc fabs.c -o fabs
Even man fabs
says link with -lm
. But I don't know why I can compile it successfully without -lm
.
If the manual says that you should link with -lm
, then you should link with -lm
. In this case your code is simple enough and the compiler is smart enough to inline it (because your system always uses the gcc built-in). Maybe it won't be able to in some cases. Some of the floating point function built-ins fall back to the library functions if they can't be trivially inlined (not fabs
, but many others).
Manuals often tell you to do things that aren't strictly necessary in all cases because it's easier to say "do X" than to say "if you do A, B, but not C, you can maybe not have to do X, but please read the manual in the next version because we will add D and B will probably change, we'll never change A (unless we change our mind)".
By linking with -lm
you ensure that your program will work on most reasonable systems for a reasonably foreseeable future. Even though it's not strictly necessary on one particular machine at this particular point in time, with this particular code, compiled with the particular options you had this time.
Because gcc will optimize some of your code. Like printf
, gcc can replace fabs
calls. To be sure, you can compile your source code with -fno-builtin
to forbid gcc from doing so:
yoones@laptop:/tmp/toto$ gcc -fno-builtin main.c
/tmp/cc5fWozq.o: In function `main':
main.c:(.text+0x37): undefined reference to `fabs'
collect2: error: ld returned 1 exit status
You can also use nm
to list your executable symbols:
yoones@laptop:/tmp/toto$ nm ./a.out
0000000000600a18 B __bss_start
0000000000600a18 b completed.6661
0000000000600a08 D __data_start
0000000000600a08 W data_start
00000000004004b0 t deregister_tm_clones
0000000000400530 t __do_global_dtors_aux
00000000006007e8 t __do_global_dtors_aux_fini_array_entry
0000000000600a10 D __dso_handle
00000000006007f8 d _DYNAMIC
0000000000600a18 D _edata
0000000000600a20 B _end
0000000000400644 T _fini
0000000000400550 t frame_dummy
00000000006007e0 t __frame_dummy_init_array_entry
00000000004007d8 r __FRAME_END__
00000000006009d0 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000400408 T _init
00000000006007e8 t __init_array_end
00000000006007e0 t __init_array_start
0000000000400650 R _IO_stdin_used
U __isoc99_scanf@@GLIBC_2.7
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000006007f0 d __JCR_END__
00000000006007f0 d __JCR_LIST__
w _Jv_RegisterClasses
0000000000400640 T __libc_csu_fini
00000000004005d0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000400576 T main
U printf@@GLIBC_2.2.5
00000000004004f0 t register_tm_clones
0000000000400480 T _start
0000000000600a18 D __TMC_END__
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With