What's the difference between gcc and g++/gcc-c++? - gcc

It seems to me that gcc can deal with both c and c++ projects,so why is g++/gcc-c++ needed?
What's the difference between g++ and gcc-c++?

gcc will compile C source files as C and C++ source files as C++ if the file has an appropriate extension; however it will not link in the C++ library automatically.
g++ will automatically include the C++ library; by default it will also compile files with extensions that indicate they are C source as C++, instead of as C.
From http://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html#Invoking-G_002b_002b:
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc; and preprocessed C++ files use the suffix .ii. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
However, the use of gcc does not add the C++ library. g++ is a program that calls GCC and treats .c, .h and .i files as C++ source files instead of C source files unless -x is used, and automatically specifies linking against the C++ library. This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations.
For example, to compile a simple C++ program that writes to the std::cout stream, I can use either (MinGW on Windows):
g++ -o test.exe test.cpp
gcc -o test.exe test.cpp -lstdc++
But if I try:
gcc -o test.exe test.cpp
I get undefined references at link time.
And for the other difference, the following C program:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int* new;
int* p = malloc(sizeof(int));
*p = 42;
new = p;
printf("The answer: %d\n", *new);
return 0;
}
compiles and runs fine using:
gcc -o test.exe test.c
But gives several errors when compiled using:
g++ -o test.exe test.c
Errors:
test.c: In function 'int main()':
test.c:6:10: error: expected unqualified-id before 'new'
test.c:6:10: error: expected initializer before 'new'
test.c:7:32: error: invalid conversion from 'void*' to 'int*'
test.c:10:9: error: expected type-specifier before '=' token
test.c:10:11: error: lvalue required as left operand of assignment
test.c:12:36: error: expected type-specifier before ')' token

As far as I know, g++ uses the correct C++ linker options whereas gcc uses the C linker options (so you may get undefined references, etc.).

Related

threading program runs with g++ but not with gcc

I have compiled a c++ code using g++ -std=c++11 -o main main.cpp -pthread and it compiled fine however if I compile the same code using gcc -std=c++11 -o main main.cpp -pthread it does not compile and throws error. The program uses threading which properly taken care of using -pthread option while compiling. For the reference I am attaching the code below. Any help is highly appreciated.
#include <iostream>
#include <thread>
class foo
{
public:
void bar(int loop_num)
{
for (int i = 0; i < loop_num; ++i) {
std::cout << "Thread executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
std::thread t1(&foo::bar, &f, 5);
t1.join();
}
If you’ve written C++ code with GCC, you’ll know that you need to use the program g++, both for compilation and linking. For multi-module programs, this means every .cpp file gets compiled with g++, and then the entire program must be linked separately using g++. If you try to link the program using gcc, it will almost work, but you’ll get a lot of “undefined reference” errors, like this:
test.cpp:(.text+0x11): undefined reference to `std::cout'
The need to use g++ to link the entire program causes trouble when you have a very complicated build process you don’t have full control of. For instance, I’m trying to link C++ code with Mercury, and I have to use the Mercury linker, which in turn calls gcc.
So just a quick tip: If you are forced to use gcc to link the program, just add the library “stdc++”, as you would any other library, and it will work. That is, add the option “-lstdc++” to your GCC linker command line. For example:
g++ -c hello.cpp
gcc -lstdc++ -o hello hello.o
I assume the error you get looks something like this:
/tmp/ccUKAq0K.o: In function `main':
main.cpp:(.text+0x59): undefined reference to `std::thread::join()'
/tmp/ccUKAq0K.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xb6): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0xcb): undefined reference to `std::ios_base::Init::~Init()'
/tmp/ccUKAq0K.o: In function `std::thread::~thread()':
main.cpp:(.text._ZNSt6threadD2Ev[_ZNSt6threadD5Ev]+0x1d): undefined reference to `std::terminate()'
(And so on.)
C++ programs which use the standard library (so most of them) need to be linked using g++, not gcc. Only the g++ compiler driver links in most of the standard library. The gcc compiler driver compiles C++ programs, just like g++, but when the linker is invoked, the program is treated as a C program, which usually leads to linker errors.
Try adding the -lrt flag after the pthread one.

How to compile a file using a shared library?

I am trying to compile a source given a .so file libfoo.so. The only thing in this library is a function that just returns a number (yeah, I know, advanced stuff). The header file equivalent (I was provided with both, but am only supposed to use the .so) is named foo.h and the function is named int foo().
My source file is main.c:
#include <stdio.h>
#include "foo.h"
int main()
{
int x = foo();
printf("%d", x);
return 0;
}
Now, when trying to compile I have the following commands:
gcc -Wall -fPIC -c main.c -o main.o
gcc -Wall -fPIC main.o -o main -lfoo -L.
The first command fails to create the object file, outputting the following error:
fatal error: foo.h: No such file or directory
I am using Ubuntu 16.04.
I have also tried exporting the current location to LD_LIBRARY_PATH as I've seen suggested on a few other answers.
export LD_LBIRARY_PATH=$LD_LIBRARY_PATH:machine/Desktop/lib_test
You need to have the interface definition from the .h file and that file must be in the current directory or a directory on the include search path.
Note that on some systems filenames and paths are case dependent.

calling functions from a different c file

actually I was compiling with multiple files. Following are the files:
file main.c -->
#include <stdio.h>
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
int main()
{
foo1();
foo2();
foo3();
}
file 1.c -->
#include <stdio.h>
void foo1(void)
{
printf("INSIDE foo1 function\n");
}
file 2.c-->
#include <stdio.h>
void foo2(void)
{
printf("INSIDE foo2 function\n");
}
Now I compiled using gcc as follows-->
gcc 1.c 2.c main.c -o main
following was the output -->
INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function
My doubt is how could main() call foo1() and foo2() when they are not declared in main.c. But now if I change main.c as follows ( writing the definition of foo3() after main()) like this:
edited main.c -->
#include <stdio.h>
int main()
{
foo1();
foo2();
foo3();
}
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
and then if I compile I get this error:
main.c:9:6: warning: conflicting types for ‘foo3’ [enabled by default]
void foo3(void)
^
main.c:6:2: note: previous implicit declaration of ‘foo3’ was here
foo3();
^
why was this error not shown earlier in case of foo1() and foo2() . Thankyou in advance.
My doubt is how could main() call foo1() and foo2() when they are not declared in main.c
Because the GCC compiler defaults to the old ANSI C (aka as C89) language, where undeclared functions are permitted and defaults to giving int result.
Try to invoke the compiler as e.g.
gcc -std=c99 -Wall -g -c main.c
or (if you want to compile all files at once)
gcc -std=c99 -Wall -g 1.c 2.c main.c -o main
You could ask for link time interprocedural optimizations with gcc -flto instead of gcc using a recent GCC, e.g. GCC 4.9 in september 2014.
This would want a C99 conforming source code where all functions should be declared.
The -Wall asks for (almost) all warnings. The -g option produces a debuggable object code (or executable for the last command compiling all files at once).
In your edited main.c when foo3 first occurrence (inside main) is encountered, the compiler guesses that it is a function returning int. When the compiler sees the definition of foo3 it rightly complains.
You could use the -Wstrict-prototypes warning option to gcc (but it is implied by -Wall which I always recommend using).
At link time, the type (and signature) of C functions does not matter. The linker just uses name to do its job (but C++ use name mangling). Of course, calling a function with the incorrect arguments or result is undefined behavior.
The good conventional practice is to have a common header file declaring all the used and public functions and types (and constants) and include that header file in your source files (this avoids to have to copy and paste these declarations several times). So you whould have a new header file myheader.h like
// file myheader.h
#ifndef MY_HEADER_INCLUDED
#define MY_HEADER_INCLUDED
void foo1(void);
void foo2(void);
void foo3(void);
#endif /*MY_HEADER_INCLUDED*/
and you would add #include "myheader.h" in all your source files (after the #include <stdio.h> directive there). Notice the include guard trick with MY_HEADER_INCLUDED.
In practice, header files usually contain comments explaining the API of your program.
Learn also about GNU make. It will ease the building of your multi-source code files programs (you just compile and build by running make). See this and that examples of Makefile. Understand that C preprocessing is the first phase of C compilation.

Why am I getting an error with gcc but not with g++ in Linux

The line of code below is giving an error with the gcc compiler even when this file is saved as check.c. The error is at the line void swap_address(int& a, int& b) as
error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
I have used this command to compile the C file: gcc -o check check.c
but the same code is working fine if I use the g++ compiler using: g++ -o check check.c
Please provide me with the reason why it is working for g++ and not for gcc.
The code:
#include <stdio.h>
void swap_value(int a, int b)
{
a=a+b;
b=a-b;
a=a-b;
}
void swap_address(int& a, int& b)
{
a=a+b;
b=a-b;
a=a-b;
}
int main()
{
int i=5,j=3;
swap_value(i,j);
printf("%d%d\n", i, j);
swap_address(i,j);
printf("%d%d\n", i, j);
return 0;
}
swap_address() has reference parameters the file has a ".c" extension, so gcc is assuming it is a C file and producing an error because reference parameters are not part of C.
g++ is taking the file as being C++, so it is happy with the reference parameters.
References are a C++ feature, they are not supported in C.
C and C++ are different programming languages.
You saved your file with .c extension, which makes gcc executable to treat it as C language file. Meanwhile you attempt use C++ features in your code (e.g references). No wonder it doesn't compile with gcc.
g++ executable unconditionally treats all files as C++ files, regardless of extension, which is why it compiles with g++.

Linker and dependencies

For a Linux/g++ project, I have a helper library ("libcommon.a") that I wrote that is used in two different programs ("client" and "server"). One particular source file among several, oshelper.cpp, has a set of unrelated utility functions:
// header file
#ifndef OSHELPER_H
#define OSHELPER_H
size_t GetConsoleWidth();
uint32_t GetMillisecondCounter();
#endif
// -----------------------------------------
// Code file
#include "commonincludes.h"
#include "oshelper.h"
size_t GetConsoleWidth()
{
struct winsize ws = {};
ioctl(0, TIOCGWINSZ, &ws);
return ws.ws_col;
}
uint32_t GetMillisecondCounter()
{
timespec ts={};
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint32_t)(ts.tv_nsec / 1000000 + ts.tv_sec * 1000);
}
Both programs link to the library that contains these functions (libcommon.a or -lcommon).
"client" program calls both the GetConsoleWidth and GetMillisecondCounter function. And since GetMillisecondCounter ultimately depends on a call to "clock_gettime", -lrt is a required parameter to the linker such that librt is linked in. This is expected.
"server" just calls GetConsoleWidth. It never calls GetMillisecondCounter. But without "-lrt" being passed, the linker complains about the unresolved reference to clock_gettime. Which is obviously fixed by passing -lrt to g++. And then "ldd server" shows that librt.so.1 is still a runtime dependency. So the linkage to clock_gettime clearly did not get optimized away.
But when I separate the implementation of GetConsoleWidth into a seperate source file (but still part of libcommon.a), the linker stops complaining about the unresolved reference to clock_gettime and no longer insists that I pass in -lrt.
It's as if the g++ linker can only cull out unused object files, but not unused function calls.
What's going on here?
Update: the compiler and linker command lines are as basic as they can get:
g++ -c oshelper.cpp
g++ -c someotherfile.cpp
etc...
ar -rv libcommon.a oshelper.o someotherfile.o ...
g++ server.cpp -lcommon -lpthread -o server
g++ client.cpp -lcommon -lrt -o client
Without special commands an .o is linked in its entirety, and thus all he dependencies are required.
You need to build the compilation units in the library with compiler flags that put all symbols in separate sections, and then call the linker with an option that "garbage collects" sections, so that only code referenced directly or indirect from main (and maybe ctors/dtors) is linked in.
I don't know the commands exactly but search for gcc parameters like -ffunction-sections -fdata-sections -fvtable-gc and -gc-section(s)

Resources