5

I've been including <string.h> all over the place and the moment I go to include <math.h> for pow() I discover that I need to modify my makefile to get access to the definition of pow.

I also do not know where I can look up more libraries if I need to include them. I randomly read that -lm flag (or at least the m of it) indicates the standard c math library, but I have no idea what any of the other standard c libraries might be called.

I just looked in user/local/lib and all I see is:

$ cd /usr/local/lib
$ ls -al
drwxr-xr-x  3 root root  4096 Apr 25  2012 .
drwxr-xr-x 10 root root  4096 Apr 25  2012 ..
drwxrwsr-x  4 root staff 4096 Oct 14 10:19 python2.7
tarabyte
  • 17,837
  • 15
  • 76
  • 117
  • oh! soooo useful @simonc. thank you! I didn't think that the man page would show what you need to link with! – tarabyte Oct 22 '13 at 18:36
  • @tarabyte I spoke too soon. Some man pages include this, others don't – simonc Oct 22 '13 at 18:39
  • As to your second question, you should be able to see libraries in `/usr/lib`. It is odd though that you don't see anything in `/usr/local/lib`, since I see a ton of files there (running OS X). You can set the `LD_LIBRARY_PATH` environment variable to a specific path if you want to point to other libraries. – limp_chimp Oct 22 '13 at 18:45
  • @limp_chimp If there's anything in `/usr/local/lib`, then you or your sysad installed it. The OS doesn't touch that directory. – Fred Foo Oct 22 '13 at 18:51
  • @larsmans the OS might not install anything in there, but there are still plenty of things that make it into there. Of course, a lot of them are symlinks, but there are plenty of library files (mostly for languages like python, ruby, nodejs, etc) which are in there. I suppose it would be correct to say that I installed these files (indirectly); however, it doesn't change my surprise that his `/usr/local/lib` is almost empty. – limp_chimp Oct 22 '13 at 19:06

4 Answers4

6

string.h is a header reference to a module of the standard library, but due to historical reasons math.h is not a header reference to a module of the standard library. Only the standard library is typically included by default in the linker when compiling programs.

At one point in time, one might substitute libm.so math.h implementations with other implementations that were better optimized for memory, CPU performance, etc. Effectively there was not a single libm.so "default" implementation. However, most systems at least provided an implementation. That implementation is in the default library location as libm.so and would be linked in with -lm.

In the event that you had a faster (perhaps even at the expense of less accurate) library that you understood you could use, you had the ability to override the system-provided math.h libm.so implementation.

The early CRAY systems (I didn't work on one) did optimize a few math implementations to not do proper "full" math operations, with the understanding that to get a 100% correct answer, you would "finish" the assembly operations with code that often wasn't important due to the number of significant digits in the computation. (From my understanding of a Cryptology Museum display in Washsington D.C.)

The problem with multiple implementations is that you now have a choice, and the standard C library is not structured to provide you with a choice of implementation.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • 1
    Your terminology is sloppy... both `string.h` and `math.h` are *standard **headers***, and the C standard requires (hosted) implementations to provide everything in both. The C standard has no concept of "library." Unix-derived systems happen to split the standard C runtime into two "libraries" (for, AIUI, entirely historical reasons) but that does not make the math functions any less standard. – zwol Oct 22 '13 at 18:55
  • I'll accept the criticism that my terminology is sloppy. It is. But,"When I use a word,' Humpty Dumpty said in rather a scornful tone, 'it means just what I choose it to mean — neither more nor less." "The question is," said Alice, "whether you can make words mean so many different things." "The question is," said Humpty Dumpty, "which is to be master— that's all." - Lewis Carroll – Edwin Buck Oct 22 '13 at 19:10
2

To give you more information on another aspect of your post, to find where the libraries are on your machine will be operating system dependent. As it appears you are using an OS with bash you will find most of your libraries in the /usr or /usr/local folders (maybe I should not say most, but it has been a default install location for many libraries I have used, such as boost). This is not the location c++ libraries tend to be installed however.

My c++ libraries were located in folders labeled lib, which made them easy to search for using the find tool. Something like find / -iname "*lib*" 2>/dev/null should help you find any locations you might have libraries installed that you will need to tell your linker about. (You can ignore the 2>/dev/null if you want to sudo the command).

I had a lot of trouble recently getting my IDE's to play nice with boost, so hopefully this helps any future troubles you might have with linking your libraries.

EDIT: I wanted to add a bit of information about how to tell your IDE's about the libraries. Using the find tool, looking for all folders named include will lead to any folders that should be included in the IDE's compiler Additional Include Directories (not all folders named include, I should clarify, but this will help find any folders with the name and the specific one you want, such as seeing /usr/local/include/boost in the search results). The libraries, which I mentioned how to find earlier, will be added in the linker section under Additional Library Directories so they know where to look for the libraries specifically.

EDIT 2: To give some information on where to find the appropriate files on Windows, the search is a bit harder. There does not seem to really be a "standard" location that developers install to (if anything it might be the home directory of the current user, but that is far from the only place used). Further, the find functionality on Windows is not as simple or useful (in my opinion). On top of that, specifically for c++ files, it will be entirely based on HOW you obtained the files. For instance, if you are using Visual Studio, they are located inside the folder for the c++ portion of Visual Studio (i.e. it is C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ on my machine) but if you are using the files you can obtain from MinGW it will be in a different location. My only advice here is to create a folder in a location of your choice (I used a folder directly inside C:) to manually install everything to that you add to your system.

Boost, for instance, allows easily changing the install path from the default at the time of install. Most (I am more comfortable saying nearly all here) tools created will have this feature, especially on Windows. Otherwise, searching the default locations specific to each utility you add or learning to use the find utility Windows provides are viable options.

Steel
  • 21
  • 5
  • Would piping your suggestion into grep be an improvement for finding specific functions I wonder? eg. somthing like: `find / -iname "*lib* | grep "functionName"`. (its been awhile since I've used ksh and vi to do command line searches :) – ryyker Oct 22 '13 at 19:02
  • 1
    @ryyker: Not really. You'd be grepping a list of library file names; function names will not appear (there's no `sqrt.lib` or anything similar, for example). Nor would `... | xargs grep ...` be likely to do much good, since library files are binaries. You might be able to put together a pipe that applies the `nm` command to each library, but first you'd want stricter filtering than `*lib*` (which would include directories and irrelevant files). – Keith Thompson Oct 22 '13 at 19:38
  • @ryyker Keith is right, while using `grep` in tandem with `find` can be extremely useful, it will not do what you are thinking. Also to clarify, as mentioned `*lib*` is a very broad filter, and will catch stuff that won't be needed at all. However, on a personal machine (work or home), there should not be that many directories and other files that will be labeled as such and `*lib*` should be sufficient when searching for libraries, in my opinion. – Steel Oct 22 '13 at 19:43
1

Standard C library functions are all defined in libc and you don't have to link it to your program as it is done automatically by your linker at linker time. The only exception to this is math functions. They are put in a separate library called libm. They were put in a separate library for historical reasons related to the Fortran compiler on UNIX (I don't have any source to support this claim).

ouah
  • 142,963
  • 15
  • 272
  • 331
  • FORTRAN guided `-lm`? Do you have a source for that? I thought it was because UNIX kernels were compiled to explicitly disallow floating point math, and not including the math library was one of the enforcement mechanisms. – jxh Oct 22 '13 at 18:41
  • Sorry, cannot remember the source but Fortran compiler on UNIX would have also used `libm` and not `libc`. – ouah Oct 22 '13 at 18:46
  • @jxh: that's nonsense, the Unix kernel never used `stdio` either but they did merge that into libc as of Unix V7. (Before that, you'd have to link it in explicitly, as well as some other utility libraries that we now consider part of the standard library. I'm not sure kernels actually linked against libc.) – Fred Foo Oct 22 '13 at 18:53
  • I did fortran to C binding in a project, long ago. We didn't use any "different" libm to do so, but there were a couple of very "crusty" libm files lying around. A few had tables to lookup and then correct for error on functions like `sin(...)` and `cos(...)`, etc. They were supposed to be "fast libm" but who knows if they were faster, as they were far too unmaintained to trust (and we hadn't used them in years). – Edwin Buck Oct 22 '13 at 18:54
  • @larsmans: I thought the kernel did use `libc`, but you are right, it would not use `stdio` facilities. – jxh Oct 22 '13 at 20:10
0

The implementation of the math library is (typically) in two parts.

<math.h> is a header file, typically /usr/include/math.h. It's C source code that tells the compiler how to generate calls to pow and other functions. It should be available by default; all you need is #include <math.h>, and the compiler will know where to find it. (So your title is a little misleading.)

The functions declared in <math.h> are implemented in a library file, which contains precompiled executable code that can be linked into your program (after it's been compiled). That library, for historical reasons, is typically not searched for by default, and you have to specify an additional -lm option to tell the linker where to find it. (This is widely considered a bug; on the other hand, not searching the math library by default can make linking very slightly faster, and most C programs don't use the math library.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631