161

What are the difference between the 3 compilers CC, gcc, g++ when compiling C and C++ code in terms of assembly code generation, available libraries, language features, etc.?

mrflash818
  • 930
  • 13
  • 24
vehomzzz
  • 42,832
  • 72
  • 186
  • 216

3 Answers3

173

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    And on OSX (Sierra 10.2 at least), it's a symlink to clang. – Josh Kodroff Apr 09 '18 at 17:22
  • For Debian buster `$ readlink -f $(which cc) $(which gcc) /usr/bin/x86_64-linux-gnu-gcc-8 /usr/bin/x86_64-linux-gnu-gcc-8` – EsmaeelE Dec 17 '20 at 16:59
  • @JoshKodroff I just did `ls -la /usr/bin | grep cc` I don't `-> clang`. Why do you think it's a symlink to `clang`? – mfaani Feb 23 '23 at 14:05
  • @mfaani: at one time, `gcc` was a link at link to `clang` (Sierra 10.12 is quite old now, released in 2018 and shouldn't still be in use). The compilers aren't necessarily linked any more; they've changed the rules (several times). On my Monterey 12.6.3 machine, both `/usr/bin/gcc` and `/usr/bin/clang` are 2 of 76 hard links to the same executable (other names include `git`, `m4`, `indent`, `swift`, `ar`, …). The rules on macOS change routinely. – Jonathan Leffler Feb 23 '23 at 16:42
  • Just to make sure I understand your 'wording'. Are you saying 1. within `/usr/bin` you have 76 executables? 2. two of those 76 executables are `clang` and `gcc`? ok. so far I'm with you. the only part of your wording that I don't understand is, 'hard links to the same executable'. You mean: "while `gcc` and `clang` are **not** symlinked anymore and point to different things. What's 'same' then? – mfaani Feb 25 '23 at 03:33
  • @mfaani: What I mean is that there are 76 files in `/usr/bin` with the same inode number. For example: `1152921500312781232 -rwxr-xr-x 76 root wheel 167120 Jan 11 00:03 gcc` and `1152921500312781232 -rwxr-xr-x 76 root wheel 167120 Jan 11 00:03 clang` and 74 other files. And yes, I'm getting a 19-digit inode number. Clearly, these all look at the name by which they're invoked and run a program installed elsewhere, mainly `/Library/Developer/CommandLineTools/usr/bin` for the executables. Those are all different sizes because they do different jobs. – Jonathan Leffler Feb 25 '23 at 19:06
  • you mean all of those 76 items are invoked using `/Library/Developer/CommandLineTools/usr/bin`? I understand how invocation works in the sense that the first param is used to direct stuff. Like that's how `swiftc` differs from `swift`. However using the same binary to process `git`, ar`, `indent` along with `swift`, `clang`, `gcc` seems too much. Like I understand what's happening. I'm clueless of its why/design. Is there anything you can point me to? – mfaani Feb 25 '23 at 20:32
  • @mfaani — No; there is a control program in `/usr/bin` with 76 different names. That control program looks at what it was invoked as and runs the corresponding command hidden in the `/Library/…/bin` directory. As a user, I type (or my `make` program runs) `gcc`, and that's `/usr/bin/gcc`, but that program is the same physical program as `/usr/bin/swiftc` and all the others, but it in turn runs `/Local/…/bin/gcc`. I'm not entirely clear why Apple does it. It would allow them to monitor what's being used more easily — I sometimes wonder whether there're delays because of that (but probably not). – Jonathan Leffler Feb 25 '23 at 22:47
  • @mfaani — Just for fun, I ran: `ln -s /usr/bin/gcc ozymandias; ./ozymandias --version`. It reports "xcode-select: Failed to locate 'ozymandias', requesting installation of command line developer tools." And a window popped up offering to install the command line tools. `xcode-select` is a separate executable — different inode number, size and only one link. (Ozymandias is the name of a poem by Percy Bysshe Shelley — _"Look on my Works, ye Mighty, and despair." Nothing besides remains. Round the decay Of that colossal Wreck, boundless and bare The lone and level sands stretch far away._) – Jonathan Leffler Feb 25 '23 at 22:56
36

CC is an environment variable referring to the system's C compiler. What it points to (libraries accessible, etc) depend on platform. Often it will point to /usr/bin/cc, the actual c complier (driver). On linux platforms, CC almost always points to /usr/bin/gcc.

gcc is the driver binary for the GNU compiler collection. It can compile C, C++, and possibly other languages; it determines the language by the file extension.

g++ is a driver binary like gcc, but with a few special options set for compiling C++. Notably (in my experience), g++ will link libstdc++ by default, while gcc won't.

Managu
  • 8,849
  • 2
  • 30
  • 36
  • 1
    Can you please explain what you mean by "driver binary"? – Edan Maor Oct 04 '09 at 15:19
  • 7
    Most C compilers, but GCC specifically, have a number of programs that do the compilation work. There is a top-level program, called 'gcc', that is the compiler driver; it parses a myriad command line options and orchestrates the other phases of the compiler - the parser/analyzer, the optimizer, the assembler and the linker, typically (the preprocessor is not usually a separate phase these days, unless you request only preprocessing). It (the compiler driver) is quite a complex program, even though it never touches a C source file itself. – Jonathan Leffler Oct 04 '09 at 15:28
  • 5
    CC is also the Sun C++ compiler - and not an environment variable. – Jonathan Leffler Oct 04 '09 at 15:39
  • 2
    SGI's C++ compiler is also CC. – alex tingle Oct 04 '09 at 18:54
  • 1
    Well, I suppose Managu is thinking that `./configure`+`make` can take an environment variable named `CC` to affect the C compiler used, but otherwise there isn't generally an environment variable by that name. – ephemient Oct 05 '09 at 00:19
  • CC is also Sun Solaris CPP compiler – Charles Chow Aug 11 '15 at 23:13
  • I had the same problem as mentioned in the post "getenv(“cc”) is returning NULL , why?" after searching for cc as an environmental variable. In the post "getenv(“cc”) is returning NULL , why?", users "aschepler," "john.jansen," and "gsamaras" seemed to all indicate that cc is not an environmental variable. When I used "env >> env_vars.txt" to read the environmental variables (in Linux) neither "cc" nor "CC" appeared as an environmental variable. – AGéoCoder Jul 24 '18 at 23:42
14

I wanna add just one information what cc in Linux. It is linked with gcc. To check it. enter image description here

Similarly, the same thing with c++.

uddhavpgautam@UbuntuServer1604:~/Desktop/c++$ whereis c++
c++: /usr/bin/c++ /usr/include/c++ /usr/share/man/man1/c++.1.gz  
uddhavpgautam@UbuntuServer1604:~/Desktop/c++$ ls -l /usr/bin/c++
lrwxrwxrwx 1 root root 21 Jul 31 14:00 /usr/bin/c++ -> /etc/alternatives/c++
uddhavpgautam@UbuntuServer1604:~/Desktop/c++$ ls -l /etc/alternatives/c++
lrwxrwxrwx 1 root root 12 Jul 31 14:00 /etc/alternatives/c++ -> /usr/bin/g++
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64