In C++, why don't I have to include anything to use the sqrt() function? - c++

I am just learning C++. Compiling with g++ version 3.2.3, "g++ hworld.cpp":
double sqrt(double);
int main(){
double x = sqrt(1515.15);
return 0;
}
That compiles fine, but if we were to replace sqrt with "sqrtfoo" the compiler would say sqrtfoo cannot be used as a function. I thought I would have to include cmath, but I guess not? Can someone please explain what my program has access to before any includes? For comparison, gcc does not allow me to do this, saying "undefined reference to 'sqrt'." Thank you.

You don't need to include cmath because your code has a prototype for sqrt in it already, the very first line.

As the existing answers explain, the double sort(double) provides a prototype to let the compiler know that the function exists.
But you also mentioned that this doesn't work under GCC. When you build a C or C++ program, the source code is compiled into object format. The object files are then linked together to form an executable.
To see this in action, try
gcc -c hello.c
This tells GCC to compile (-c) the source file hello.c. Assuming that hello.c exists and has no errors, you'll find hello.o in the current directory. Now try
gcc -o hello hello.o
This tells GCC to link hello.o with the appropriate system libraries, and to generate an output file called "hello". If hello.c uses math functions, you'll also need to link in the math library:
gcc -o hello hello.o -lm
"-l" is used to tell gcc to include extra libraries (beyond the default "libc" C library). "m" refers to "libm", which is the math library containing sqrt. If your program uses only one source file it's common to ask implicitly GCC to compile and link in a single command:
gcc -o hello hello.c -lm
Now to your question. GCC won't compile the above code because you haven't asked it to link in the math library. But g++ is okay with it. There's a very similar question already on Stack Overflow. According to its accepted answer,
the C++ runtime libstdc++ requres libm, so if you compile a C++
program with GCC (g++), you will automatically get libm linked in.
Since "libstdc++" is the C++ language runtime library, it's included by g++ by default. And as it depends on libm, the linker automatically loads libm while producing the final binary program.

Header files hold only declarations (signatures), and you've included one in the first line (prototype: double sqrt(double)).
The compiler compiles it just fine, because you've stated that somewhere this function is defined. The step that occurs after compiling is responsible for actually looking for that function definition. It's called linking, and during that phase linker lookups those definitions. In case of sqrtfoo it cannot find anything, whereas in case of sqrt it finds it in some standard library (I do not know the details here).

Related

Undefined reference when combining C++ and Fortran [duplicate]

I am trying to link a .o file generated using g++ and another .o file generated using gfortran.
g++ -c mycppcode.cpp
produces the file mycppcode.o and the command
gfortran -c myfortrancode.f
produces the file myfortrancode.o
When I link these two files to get an output file
g++ -O mycppcode.o myfortrancode.o
I get the following error
Undefined symbols for architecture x86_64:
"__gfortran_pow_c8_i4", referenced from:
Could some one help me with this? Should I use another compiler? Also, I would like to know what functions or subroutines call "__gfortran_pow_c8_i4", so that I can try to avoid these functions or subroutines in fortran in future.
The following assumes you are using the GNU compiler tools. Things may be slightly different if you are using other compilers.
You can use either compiler to link the two together, but you need to provide the appropriate libraries.
Typically, you can use either
gfortran fortobj.o cppobj.o -lstdc++
or
g++ fortobj.o cppobj.o -lgfortran
This assumes that you are using a setup where both compilers know about each other's libraries (like if you installed through a linux repository).
In the case of the OP the C compilers came from XCode and gfortran is from homebrew. In that case, gfortran knows about the g++ libraries (since they were used to compile the compiler), but g++ doesn't know about the gfortran libraries. This is why using gfortran to link worked as advertised above. However, to link with g++ you need to add the path to libgfortran.* when you call the linker using the -L flag, like
g++ fortobj.o cppobj.o -L/path/to/fortran/libs -lgfortran
If for some reason your gfortran compiler is unaware of your g++ libs, you would do
gfortran fortobj.o cppobj.o -L/path/to/c++/libs -lstdc++
Note that there shouldn't be any difference in the final executable. I'm no compiler expert, but my understanding is that using the compiler to link your objects together is a convenience for calling the linker (ld on UNIX-like OS's) with the appropriate libraries associated with the language you are using. Therefore, using one compiler or the other to link shouldn't matter, as long as the right libraries are included.

lstd++ & extern - calling C++ from C

I have wrapped my C++ header file in an extern "C" block to allow calling C++ functions from C. I have included the proper header files in the proper places. It works if I do something like the following:
g++ -c cpp_src.cc
gcc -c c_src.c
gcc -o c_exe c_src.o cpp_src.o -lstdc++
But if I remove the -lstdc++ from the last line, I get a bunch of errors. Because of reasons beyond my control, I cannot add the -lstdc++ flag. Is there a way to get the above to work without -lstdc++? What exactly is lstdc++, as in how does the gcc use it while linking with g++ compiled code?
Also, cpp_src.cc uses STL, if that makes a difference.
If you really need to have an object file that you can link with gcc without using -lstdc++, you can do an incremental link of your C++ object file with -lstdc++ and then use the result of that on your gcc link line. Something like:
ld -i -static cpp_src.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -lstdc++ -o cpp_withstdlib.o
This will link your C++ object file with the standard C++ library and produce a new object file (cpp_withstdlib.o) that contains all the standard C++ library stuff you need, so can be linked on the gcc command line without needing -lstdc++
The tricky part is the -L option -- you need to figure out where g++ has stashed its standard library, as it generally doesn't put it in the standard /usr/lib location. The above is for an Ubuntu 14.04 machine. On most Linux machines, you can find it with locate libstdc++.a
You're generally just better off using g++ to link C++ code, as it knows all the right paths and won't make little mistakes that result in a binary that superficially appears to work, but is actually incorrect.
Using Josh's suggestion, you can do:
ld -i -static cpp_src.o `g++ -print-file-name=libstdc++.a` -o cpp_withstdlib.o
which is a bit cleaner, and could readily be done in a Makefile.
-lstdc++ causes the linker to link to libstdc++, which is gcc's implementation of the C++ standard library. If your code uses any symbols from the standard library (it uses the standard library, and not all code is inlined from headers), it must link libstdc++ (or whichever standard library implementation you use).
You can avoid the standard library, or you can link against the system standard library, or you can statically link a copy of the standard library into your program.

Static linking to libcrypto++, with g++

I am trying to compile a program on my system with Debian Wheezy and g++4.7. I want it to be able to run on another system with Debian Squeeze (and no recent g++). I can't compile the program on the Squeeze, because I use certain C++11 features the old g++ does not support, as well as a new Boost version and libcrypto++9.
As far as I understand the usual way to get around this problem is to static link the libraries not supported at the other system, in my case libstdc, boost and crypto++.
My (linking) compiler call right now is
g++-4.7 .obj/btcmirco.o -Wl,-Bstatic -lboost_program_options -lboost_system -lcrypto++ -Wl,-Bdynamic -lcurl -static-libgcc -std=c++11 -o MyProgram
However I seem to have missed something, because it throws a lot of undefined reference errors. It works fine if I dynamic link to crypto++ (and only static link libstdc and boost).
Can anyone tell me whats wrong, or if there is a fundamental error in my approach?
The linker errors I get are (shorted):
`.text._ZN8CryptoPP22BufferedTransformationD2Ev' referenced in section `.text._ZN8CryptoPP22BufferedTransformationD1Ev[_ZN8CryptoPP22BufferedTransformationD1Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o): defined in discarded section `.text._ZN8CryptoPP22BufferedTransformationD2Ev[_ZN8CryptoPP22BufferedTransformationD5Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o)
`.text._ZN8CryptoPP25MessageAuthenticationCodeD2Ev' referenced in section `.text._ZN8CryptoPP25MessageAuthenticationCodeD1Ev[_ZN8CryptoPP25MessageAuthenticationCodeD1Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o): defined in discarded section `.text._ZN8CryptoPP25MessageAuthenticationCodeD2Ev[_ZN8CryptoPP25MessageAuthenticationCodeD5Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o)
I experienced the same problem and this has to do with the fact that you are trying to mix code generated by g++-4.7 (your program) with code generated by a previous version of g++ (cryptopp library).
The reason behind this is that when you execute compile the library executing make command, it uses the default version of g++ set up for your system, usually the one that comes with the OS.
In order to solve the issue what you should do is compile cryptopp library with g++-4.7.
For that, compile the library by executing make CXX=g++-4.7. The resulting static library shouldn't give you the error when being linked with your code.

equivalent gcc flags for g++ call

I'm playing around with a toolchain that seems to wrap gcc (qcc), but also uses g++ for a few things. This caused a bit of confusion when I couldn't link libs I built with g++ using g(q)cc even though it was for the same architecture (due to missing lib errors). After a bit more research, I found that g++ is basically gcc with a few default flags and a slightly different interpretation mechanism for file extensions (there may be other differences I've glanced over). I'd like to know exactly which flags can be passed to gcc to amount to the equivalent g++ call. For instance:
g++ -g -c hello.cpp // I know at the very least that this links in stl
gcc -g -c -??? // I want the exact same result as I got with g++... what flags do I use?
The way the tool chain is set up makes it sort of difficult to simply replace the gcc calls with g++. It'd be much easier to know which flags I need to pass.
The differences between using gcc vs. g++ to compile C++ code is that (a) g++ compiles files with the .c, .h, and .i extensions as C++ instead of C, and that (b) it automatically links with the C++ standard library (-lstdc++). See the man page.
So assuming that you're not compiling .c, .h., or .i files as C++, all you need to do to make gcc act like g++ is add the -lstdc++ command line option to your linker flags. If you are compiling those other files as C++, you can add -x c++, but I'd advise you instead to rename them to use .cc or .ii files (.h can stay that way, if you're using precompiled headers).

How do I source/link external functions in C or C++?

EDIT: I suppose I should clarify, in case it matters. I am on a AIX Unix box, so I am using VAC compilers - no gnu compilers.
End edit
I am pretty rusty in C/C++, so forgive me if this is a simple question.
I would like to take common functions out of a few of my C programs and put them in shared libraries or shared objects. If I was doing this in perl I would put my subs in a perl module and use that module when needed.
For the sake of an example, let's say I have this function:
int giveInteger()
{
return 1034;
}
Obviously this is not a real world example, but if I wanted to share that function, how would I proceed?
I'm pretty sure I have 2 options:
Put my shared function in a file, and have it compile with my main program at compile time. If I ever make changes to my shared function, I would have to recompile my main program.
Put my shared function in a file, and compile it as a shared library (if I have my terms correct), and have my main program link to that shared library. Any changes I make to my shared library (after compiling it) would be integrated into my main program at runtime without re-compiling my main program.
Am I correct on that thinking?
If so, how can I complish either/both of those methods? I've searched a lot and I seem to find information how how I could have my own program link to someone else's shared library, but not how to create my own shared functions and compile them in a way I can use them in my own program.
Thanks so much!
Brian
EDIT: Conclusion
Thanks everyone for your help! I thought I would add to this post what is working for me (for dynamic shared libraries on AIX) so that others can benefit:
I compile my shared functions:
xlc -c sharedFunctions.c -o sharedFunctions.o
Then make it a shared object:
xlc -qmkshrobj -qexpfile=exportlist sharedFunctions.o
xlc -G -o libsharedFunctions.so sharedFunctions.o -bE:exportlist
Then link it another program:
xlc -brtl -o mainProgram mainProgram.c -L. -lsharedFunctions
And another comment helped me find this link, which also helped:
http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/proguide/ref/compile_library.htm
Thanks again to all who helped me out!
Yeah you are correct. The first is called a static library, while the second is called a shared library, because the code is not bound to the executable at compile time, but everytime again when your program is loaded.
Static library
Compile your library's code as follows:
gcc -c *.c
The -c tells the program not to link the object file, but just leaves you with object files for each .c file that was compiled. Now, archive them into one static library:
ar rcs libmystuff.a *.o
man ar will tell you what the rcs options mean. Now, libmystuff.a is a archive file (you can open it with some zip-file viewers) which contain those object files, together with an index of symbols for each object file. You can link it to your program:
gcc *.c libmystuff.a -o myprogram
Now, your program is ready. Note that the order of where the static libraries appear in the command matter. See my Link order answer.
Shared library
For a shared library, you will create your library with
gcc -shared -o libmystuff.so *.c
That's all it takes, libmystuff.so is now a shared object file. If you want to link a program to it, you have to put it into a directory that is listed in the /etc/ld.so.conf file, or that is given by the -L switch to GCC, or listed in the LD_LIBRARY_PATH variable. When linking, you cut the lib prefix and .so suffix from the library name you tell gcc.
gcc -L. -lmystuff *.c -o myprogram
Internally, gcc will just pass your arguments to the GNU linker. You can see what arguments it pass using the -### option: Gcc will print the exact arguments given to each sub process.
For details about the linking process (how some stuff is done internally), view my Linux GCC linker answer.
You've got a third option. In general, your C++ compiler should be able to link C routines. The necessary options may vary from compiler to compiler, so R your fine M, but basically, you should be able to compile with g++ as here:
$ g++ -o myapp myapp.cpp myfunc.c giveint.c
... or compile separately
$ gcc -c myfunc.c
$ gcc -c giveint.c
$ g++ -c myapp.cpp
$ g++ -o myapp myapp.o myfunc.o
You also need to include your declaration of the functions; you do that in C++ as
extern "C" {
int myfunc(int,int);
int giveInterger(void);
}
You need to distinguish between recompiling and relinking.
If you put giveInteger() into a separate (archive) library, and then modify it later, you'll (obviously) need to recompile the source file in which it is defined, and relink all programs that use it; but you will not need to recompile such programs [1].
For a shared library, you'll need to recompile and relink the library; but you will not have to relink or recompile any of the programs which use it.
Building C++ shared libraries on AIX used to be complicated; you needed to use makeC++SharedLib shell script. But with VAC 5.0 and 6.0 it became quite easy. I believe all you need to do is [2]:
xlC -G -o shr.o giveInteger.cc
xlC -o myapp main.cc shr.o
[1] If you write correct Makefile (which is recommended practice), all of this will happen automatically when you type make.
[2] There is a certain feature of AIX which may complicate matters: by default shared libraries are loaded into memory, and "stick" there until subsequent reboot. So you may rebuild the shr.o, rerun the program, and observe "old" version of the library being executed. To prevent this, a common practice is to make shr.o world-unreadable:
chmod 0750 shr.o