why use g++ instead of gcc to compile *.cc files?
It depends on what exactly you changed in the makefile. gcc
/ g++
is really just a front-end driver program which invokes the actual compiler and / or linker based on the options you give it.
If you invoke the compiler as gcc
:
- it will compile as C or C++ based on the file extension (
.c
, or.cc
/.cpp
); - it will link as C, i.e. it will not pull in C++ libraries unless you specifically add additional arguments to do so.
If you invoke the compiler as g++
:
- it will compile as C++ regardless of whether or not the file extension is
.c
or.cc
/.cpp
; - it will link as C++, i.e. automatically pull in the standard C++ libraries.
(see the relevant bit of the GCC documentation).
Here's a simple program which detects whether or not it has been compiled as C or C++.
(It makes use of the fact that a character constant has the size of an int
in C, or a char
in C++. sizeof(char)
is 1 by definition; sizeof(int)
will generally be larger - unless you're using an obscure platform with >= 16-bit bytes, which you're probably not.)
I've called it test.c
and copied it as test.cc
as well:
$ cat test.c
#include <stdio.h>
int main(void)
{
printf("I was compiled as %s!\n", sizeof('a') == 1 ? "C++" : "C");
return 0;
}
$ cp test.c test.cc
$
Compiling and linking test.c
with gcc
, and test.cc
with g++
, works as expected:
$ gcc -o test test.c
$ ./test
I was compiled as C!
$ g++ -o test test.cc
$ ./test
I was compiled as C++!
$
Compiling and linking test.cc
with gcc
doesn't work: it compiles the code as C++ because the file ends in .cc
, but fails at the link stage:
$ gcc -o test test.cc
/tmp/ccyb1he5.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status
$
which we can prove by separately compiling with gcc
, and linking with g++
(to pull in the right libraries):
$ gcc -c test.cc
$ g++ -o test test.o
$ ./test
I was compiled as C++!
$
...gcc
has compiled the code as C++ rather than C, because it had a .cc
file extension.
Whereas g++
does not compile .c
files as plain C:
$ g++ -o test test.c
$ ./test
I was compiled as C++!
$
Is it possible to use hash lines instead of every single cmdline argument passed to GCC?
I have trouble supplying each cmdline options everywhere.
Why? Are you using some build automation tool like GNU make? I believe you should use it, then it is just a matter to add a few appropriate lines in your Makefile
(probably something like adding a line such as CXXFLAGS += -DHAVE_CONFIG_H -O2 -std=c++11
)
Are all cmdline arguments replaceable by # lines? If not, what args are replaceable?
You mean replaceable by preprocessor directives. Read documentation of cpp
Actually, most compiler options are not replaceable by preprocessor directives; notably
-std=
-L
and-l
and any other options for the linker-I
and similar options for include directories
However, -O2
and some other optimization flags are settable by function attributes e.g. __attribute__((optimize("O2"))
(see this) and by function specific option pragmas e.g. #pragma GCC optimize "-O2"
. Notice that this is specific to GCC.
I recommend spending a few hours reading the documentation of GCC.
You might also perhaps change your spec file, but I don't recommend doing that.
Why would one ever want to compile with -O2 instead of -O3
Size. Of course if size does really matters (sometimes is does, like embedded), one would use -Os
. But main difference at O3 is the (from you already mentioned) inlining. This can increase the generated code size (but it is faster). Maybe you want speed, but not at all (space) cost? Otherwise I would see no reason why not to use O3 (except you know of a gcc compiler bug that only occurs in your code at O3, but as long as you dont have an error, you cant reproduce at O2, I would not care).
Unable to resolve symbol
That _ZNSt8ios-base4InitD1Ev
is not a C symbol but a C++ one.
$ echo _ZNSt8ios-base4InitD1Ev | c++filt
Gives no clue, but if you replace the -
with a _
(a typo, maybe?):
$ echo _ZNSt8ios_base4InitD1Ev | c++filt
std::ios_base::Init::~Init()
So that is the destructor of an internal class of the C++ STD library. So you should check the libstdc++.so
library instead libc.so
.
My advice is to just compile your program using G++, so the C++ library is properly initialized. It is not intended to be loaded dynamically, and that's why the segmentation fault.
why use gcc and g++ compiler drivers for c and c++
The only differences between gcc and g++ are that:
- when the driver is used to invoke the linker, g++ causes libstdc++ to be linked as part of "stdlibs", while gcc will link only libc.
- g++ will compile .c, .h and .i files as C++ unless the
-x
option is specified.
Both drivers will compile C or C++ depending on either the filename extension, or command-line switches. If you invoke the compiler-driver for compilation only and invoke the linker (ld) directly, using gcc
or g++ -x
, it makes no difference which you use.
Equally, if you invoke the gcc driver for C++ code and explicitly link stdlibc++ it also makes no difference - so long as your crt0.o is not C-only - a C++ runtime start-up must invoke global static constructors before main()
) - this is likely to already be the case.
The definitive word from the documentation:
3.3 Compiling C++ Programs
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 automatically specifies linking against the C++
library. It treats ‘.c’, ‘.h’ and ‘.i’ files as C++ source files
instead of C source files unless -x is used. This program is also
useful when precompiling a C header file with a ‘.h’ extension for use
in C++ compilations. On many systems, g++ is also installed with the
name c++.When you compile C++ programs, you may specify many of the same
command-line options that you use for compiling programs in any
language; or command-line options meaningful for C and related
languages; or options that are meaningful only for C++ programs. See
Options Controlling C Dialect, for explanations of options for
languages related to C. See Options Controlling C++ Dialect, for
explanations of options that are meaningful only for C++ programs.
If you want to use just one, I suggest you use gcc and separately invoke the linker or explicitly link -libstdc++. That way the compilation mode will be dependent on the filename extension. Using g++ -x
to compile C code is just going to cause confusion.
ming32-make is using g++ instead of cc or gcc to compile a .c source file
mingw32-make (correctly IMO) treats the file system as case insensitive, so foo.c and FOO.C refer to the same file.
Your makefile lacks any explicit rule for your hello_world goal, so built-in implicit rules must be used; it seems that the COMPILE.C rule is being matched for hello_world.c, before the COMPILE.c rule; COMPILE.C is a default rule for compiling C++, so the appropriate compiler is used.
As you note, setting CXX = gcc is kludgy, and fundamentally wrong; it will break if your project expands to requiring mixed C and C++ components. A more appropriate solution is to provide your own rule ... either an explicit rule, or a pattern rule, to direct mingw32-make to use $(CC) for compiling *.c (and *.C) files, so that the built-in default rules will not apply. You can then keep CXX = g++ for compiling any *.cpp files, (recommended for compatibility with MSVC convention), which your project may include.
What is the difference between g++ and gcc?
gcc
and g++
are compiler-drivers of the GNU Compiler Collection (which was once upon a time just the GNU C Compiler).
Even though they automatically determine which backends (cc1
cc1plus
...) to call depending on the file-type, unless overridden with -x language
, they have some differences.
The probably most important difference in their defaults is which libraries they link against automatically.
According to GCC's online documentation link options and how g++ is invoked, g++
is equivalent to gcc -xc++ -lstdc++ -shared-libgcc
(the 1st is a compiler option, the 2nd two are linker options). This can be checked by running both with the -v
option (it displays the backend toolchain commands being run).
What is the main reason not to compile c code with g++?
To your generic question, there's no simple answer. C++ only supports a subset of C. If you want to write code that's valid and has the same sematics in both languages, you're very limited. Some examples of C code that's not valid C++ are:
Code that uses keywords of C++ that don't have a special meaning in C like
class
,this
,new
etc. To avoid confusion, you normally try to avoid these keywords in C, but it's of course not necessary.C has designated struct and array initializers and they are often a good idea in a typical C project. You could write for example
struct foo {int a; char b; short c; };
struct foo x = { .b = 'x', .c = 42 };this isn't valid C++.
In C, you must write
struct foo
to refer to a structure with tag foo, while C++ allows to just writefoo
. This has a strange consequence when it comes totypedef
s. In C, you could havestruct foo;
typedef struct bar foo;This is just an example, the code is confusing of course. But it's invalid code in C++, because it would be unclear what you refer to when just writing
foo
. Therefore, in C++, atypedef
with the same name as astruct
tag must refer to the exact same type.C supports flexible array members as the last element of a
struct
like this:struct foo { int x; int a[]; }
The size of
a
is determined when you allocate memory for that struct (addingn * sizeof(int)
). This feature doesn't exist in C++In C, pointer casts are almost always wrong, while they can be used in C++ for casting between a base class and a derived one. Therefore, C has the concept of a generic pointer
void *
that can be converted without a cast. In C++, converting to and fromvoid *
requires a cast like with any other pointer type.
These are just the examples that I could think of immediately, there are probably more. So yes, it's never a good idea to compile C code with a C++ compiler.
I used c in a project, and after some study, I found better method with some c++ libraries, but I really don't want to rewrite the code
For this problem, there's another simple solution. Divide your code into multiple translation units. There's no problem at all with a mixed C/C++ project, as long as the C and C++ source files are distinct.
So that means you factor out all the code using your C++ library in a C++ file and compile only that file with a C++ compiler. For the public interface of that C++ module, use extern "C"
declarations and guard them with an #ifdef __cplusplus
to hide them from the C compiler.
The structure could look like this (very simplified), if the part using C++ is in a translation unit called module
here:
module.h:
#ifndef MODULE_H
#define MODULE_H
#ifdef __cplusplus
// the C++ compiler will see this causing all declarations in the block to have C linkage,
// the C compiler won't see it (skipped by the preprocessor)
extern "C" {
#endif
int module_foo(int arg);
#ifdef __cplusplus
}
#endif
#endif
module.cpp:
#include "module.h"
#include <mycpplib> // example
int module_foo(int arg)
{
// some C++ code using your C++ library
}
main.c:
#include "module.h"
int main(void)
{
int x = module_foo(42);
}
You could build a complete program like this:
gcc -c -omain.o main.c
g++ -c -omodule.o module.cpp
# link them together, using the C++ library libmycpplib:
g++ -oprogram main.o module.o -lmycpplib
Difference between CC, gcc and g++?
The answer to this is platform-specific; what happens on Linux is different from what happens on Solaris, for example.
The easy part (because it is not platform-specific) is the separation of 'gcc' and 'g++':
- gcc is the GNU C Compiler from the GCC (GNU Compiler Collection).
- g++ is the GNU C++ Compiler from the GCC.
The hard part, because it is platform-specific, is the meaning of 'CC' (and 'cc').
- On Solaris, CC is normally the name of the Sun C++ compiler.
- On Solaris, cc is normally the name of the Sun C compiler.
- On Linux, if it exists, CC is probably a link to g++.
- On Linux, cc is a link to gcc.
However, even on Solaris, it could be that cc is the old BSD-based C compiler from /usr/ucb
. In practice, that usually isn't installed and there's just a stub that fails, wreaking havoc on those who try to compile and install self-configuring software.
On HP-UX, the default 'cc' is still a K&R-only C compiler installed to permit relinking of the kernel when necessary, and unusable for modern software work because it doesn't support standard C. You have to use alternative compiler names ('acc' IIRC). Similarly, on AIX, the system C compiler goes by names such as 'xlc' or 'xlc32'.
Classically, the default system compiler was called 'cc' and self-configuring software falls back on that name when it doesn't know what else to use.
POSIX attempted to legislate its way around this by requiring the programs c89 (originally) and later c99 to exist; these are the compilers compatible with the ISO/IEC 9899:1989 and 9899:1999 C standards. It is doubtful that POSIX succeeded.
The question asks about the differences in terms of features and libraries. As before, the answer is platform specific in part, and generic in part.
The big divide is between the C compilers and the C++ compilers. The C++ compilers will accept C++ programs and will not compile arbitrary C programs. (Although it is possible to write C in a subset that is also understood by C++, many C programs are not valid C++ programs). Similarly, the C compilers will accept C programs and will reject most C++ programs (because most C++ programs use constructs not available in C).
The set of libraries available for use depends on the language. C++ programs can usually use C libraries on a given platform; C programs cannot usually use C++ libraries. So, C++ has a larger set of libraries available.
Note that if you are on Solaris, the object code produced by CC is not compatible with the object code produced by g++ -- they are two separate compilers with separate conventions for things such as exception handling and name mangling (and the name mangling is deliberately different to ensure that incompatible object files are not linked together!). This means that if you want to use a library compiled with CC, you must compile your whole program with CC. It also means that if you want to use one library compiled with CC and another compiled with g++, you are out of luck. You have to recompile one of the libraries at least.
In terms of quality of assembler generated, the GCC (GNU Compiler Collection) does a very good job. But sometimes the native compilers work a bit better. The Intel compilers have more extensive optimizations that have not yet been replicated in GCC, I believe. But any such pontifications are hazardous while we do not know what platform you are concerned with.
In terms of language features, the compilers all generally hew fairly close to the current standards (C++98, C++2003, C99), but there are usually small differences between the standard language and the language supported by the compiler. The older C89 standard support is essentially the same (and complete) for all C compilers. There are differences in the darker corners of the language. You need to understand 'undefined behaviour', 'system defined behaviour' and 'unspecified behaviour'; if you invoke undefined behaviour, you will get different results at different times. There are also many options (especially with the GCC) to tweak the behaviour of the compiler. The GCC has a variety of extensions that make life simpler if you know you are only targetting that compiler family.
Compiling a .cpp file with c++ command instead of g++ (Linux)
Shouldn't it throw an error saying there is no c++ command available? and suggest us to use g++?
Weeelll, there are no regulations or standards that restrict or require c++
command to do anything, so there is no "should" or "shouldn't". However, it would be strongly expected that c++
is a working C++ compatible compiler, that supports similar or same flags as cc
does.
does the terminal replace our c++ hello.cpp with g++ hello.cpp internally?
A terminal is the device that displays things. Terminal does not replace it, it has no effect on it.
Most probably your system designer, but maybe administrator or publisher or distributor or package designer (or anyone in the chain), configured your system to provide a command named c++
. Usually, that command is a symbolic link to a working C++ compiler, usually g++ on Linux systems. On my system, /usr/bin/c++
program is just installed with package named gcc
, but some systems allow it to be configurable.
It shouldn't do that right?
As stated above, terminal shouldn't replace commands, it has no effect on it.
This is expected since
It is expected since there is no command named c
. There are endless other unknown commands.
cc
is the good old name for a C compiler. c99
is the standardized name of C99 compatible compiler.
Why am not getting a similar error for the c++ hello.cpp?
Because a command named c++
exists on your system.
Related Topics
Checking If a Binary Compiled with "-Static"
Linux Ssh Bash Fork Retry: No Child Processes
Uses for This Bash Filename Extraction Technique
Linux Desktop Shortcut and Icon from Install
Bash: Loop Until Command Exit Status Equals 0
How to Use Systemd to Restart a Service When Down
Executing Exe or Bat File on Remote Windows Machine from *Nix
Command to Measure Tlb Misses on Linux
How to Search for a Particular String from a .Gz File
Copy and Overwrite a File in Shell Script
How to Execute Shell Builtin from Scala
Bash Script Does Not Continue to Read The Next Line of File
Linux Service Can't Load Library Path in The /Etc/Ld.So.Conf.D
Different CPU Cache Size Reported by /Sys/Device/ and Dmidecode
Install Library in Home Directory