使用“cc”和“gcc”作为GCC的调用方式有什么区别?

72
我知道在大多数GNU/Linux系统上,可以通过命令行中的“cc”(而不是“gcc”)来调用GCC。在以一种方式调用与另一种方式调用GCC之间是否存在任何差异呢?例如,我知道通过名称"g++"而不是"gcc"调用GCC会导致GCC表现不同(它将.c文件视为C++源并链接C++标准库),那么"gcc"与"cc"之间是否存在类似的行为差异?
编辑:到目前为止收到的所有答案都没有明确回答GCC是否会因为以某种方式调用而产生不同的行为。然而,建议查看源代码以检查其行为的想法引导我走上了这条路。基于我在那里发现的内容,我现在相信答案是:
没有。 GCC无论是通过“gcc”还是“cc”调用时行为都是相同的。

似乎 gawk 和 awk、gmake 和 make 等之间没有区别。我会认为它们总是相等的。在 Solaris 系统上,我听说 make 和 gmake(GNU make)不同。或许在某些系统上,gcc 和 cc 也有类似情况。 - Johannes Schaub - litb
11个回答

35

仅为了好玩,我刚刚追踪了一下gcc内部如何使用argv[0]main.c -> top_lev.c -> opts.c -> langhooks.c),似乎目前只是用于向malloc报告失败时的内容。如果argv[0]不是gcc,貌似没有任何行为变化。


4
我对此唯一的问题是,“cc --version”与“gcc --version”输出略有不同(它说“cc”而不是“gcc”)。因此,其中某些内容必须查看argv [0]。 - Dan Moulding
15
你的回答激发了我自己查看源代码。我发现argv [0]确实被分配给“programname”,它最终会在其他一些函数中传递(并存储在环境中)。尽管我没有进行彻底的搜索,但据我所见,它仅用于显示目的(例如在“--version”输出,“usage”输出,错误消息等中)。 - Dan Moulding
我刚刚注意到这只有在cc和gcc是相同的可执行文件时才成立。系统可能有不同的二进制文件吗?想象一下,cc可能链接到clang二进制文件,而gcc则链接到gcc。诚实地说,我不知道。 - Johannes Schaub - litb

15
我认为cc(指向一些旧的SUS规范的链接)旨在成为系统编译器的供应商中立接口。它被标记为遗留接口。

c89实用程序提供了与ISO C标准的接口,但cc实用程序接受C语言的未指定方言:它可能是标准C、常用C或其他某种变体。可移植的C程序应该按照ISO C标准编写,并使用c89进行编译。

POSIX有一个叫做c99的实用程序,我相信它是c89的后继者。它说:

c99实用程序基于最初引入ISO POSIX-2:1993标准的c89实用程序。 从c89到c99的一些更改包括修改标准库部分的内容以考虑新的头文件和选项;例如,在“-lrt”操作数中添加了-lrt,并添加了-ltrace操作数以进行跟踪函数。

我并不太熟悉所有这些不同的标准,但看起来较新的SUSv3(POSIX:2004)和最新的POSIX:2008(似乎还没有SUS号码)不再规定叫做cc的工具,而是只规定了叫做c99的工具。顺便说一下,我的Linux系统(Arch_Linux)包含了c99的手册页,但没有c89,只包含一个叫做cc的工具,但既没有c89也没有c99。很混乱 :)


1
有趣的链接。应该有人告诉GNU Make的开发者,因为如果你不覆盖${CC},它仍然会调用“cc”作为默认值。显然,他们应该使用其他实用程序作为默认值之一。根据标准,c89似乎应该是首选实用程序。 - Dan Moulding
1
另一方面,既然那是在1997年编写的,也许现在首选的实用程序应该是c99。 - Dan Moulding
1
是的,SUSv3不再包含c89。只有我提供链接的旧版本(SUSv2)才建议使用它。 - Johannes Schaub - litb

12

在我的 Mac 上使用 man gcc 命令:

在 Apple 版本的 GCC 中,cc 和 gcc 实际上都是指向命名为 gcc-version 的编译器的符号链接。类似地,c++ 和 g++ 是指向命名为 g++-version 的编译器的链接。

基于这个,我会认为 cc 和 gcc 的行为是相同的。


17
在Unix世界中,将多个链接设置到同一个可执行文件是很常见的。根据调用时使用的名称,它会更改一些默认设置。 - Javier
哇,只有一个没有解释的踩 - 非常有帮助...也许他们不喜欢什么? - stefanB
1
也许他们不知道Mac OS X是完全符合POSIX标准的Unix系统。 - stefanB
8
也许他们认为以下逻辑链很容易引起混淆:“符号链接到同一个可执行文件 -> 相同的行为”。例如,在最小系统上,所有基本的命令行工具都可以链接到 busybox,但它们仍然作为完全独立的工具运行。 - EFraim

11
今天我也有同样的疑问,我试着自己找到了答案: which - 确定可执行文件的位置 file - 确定文件类型
$ which cc
 /usr/bin/cc

$file /usr/bin/cc
 /usr/bin/cc: symbolic link to '/etc/alternatives/cc'

$file /etc/alternatives/cc
 /etc/alternatives/cc: symbolic link to '/usr/bin/gcc'

$which gcc
 /usr/bin/gcc

所以,基本上 cc 指向 gcc
你也可以使用 cc -vgcc -v 进行检查。如果它们打印出相同的内容,那就意味着它们完全相同。

5
注意Javier对stefanB答案的评论--Unix会将程序的“程序名称”作为第0个命令行参数提供给程序,并且Unix中的许多程序都设置有从许多不同名称的符号链接,并根据调用它们时使用的名称来更改它们的行为。 (例如,gunzip是指向gzip的链接,但如果您调用gzip,则它会压缩文件,而如果您调用gunzip,则它会解压缩文件。)因此,如果您通过名为“cc”的符号链接运行GCC,则完全有可能会导致其行为发生变化。 - Brooks Moses

7
即使gcc在argv [0]的值不同的情况下操作相同,但并非所有软件都会在您指定编译器时以相同的方式运行。
在构建zlib 1.2.5在RHEL 5.5(gcc 4.1.2)时:
$ md5sum $(which cc)
69a67d3029b8ad50d41abab8d778e799  /usr/bin/cc
$ md5sum $(which gcc)
69a67d3029b8ad50d41abab8d778e799  /usr/bin/gcc

但是:
$ CC=$(which cc) ./configure
Checking for shared library support...
Tested /usr/bin/cc -w -c -O ztest20557.c
Tested cc -shared -O -o ztest20557.so ztest20557.o
/usr/bin/ld: ztest20557.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
ztest20557.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
No shared library support; try without defining CC and CFLAGS
Building static library libz.a version 1.2.5 with /usr/bin/cc.
Checking for off64_t... Yes.
Checking for fseeko... Yes.
Checking for unistd.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.

同时:

$ CC=$(which gcc) ./configure
Checking for shared library support...
Building shared library libz.so.1.2.5 with /usr/bin/gcc.
Checking for off64_t... Yes.
Checking for fseeko... Yes.
Checking for unistd.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.
Checking for attribute(visibility) support... Yes.

配置脚本没有考虑到Linux系统上的cc可能是gcc。因此,在做出假设时要小心谨慎。

2
这是不言而喻的。编译器没有表现出任何不同。这是configure脚本的一个缺点。该脚本知道gcc可以生成共享库,并且它知道在Linux上编译共享库时,gcc需要-fPIC选项。如果编译器不是gcc,那么configure将尝试测试编译器是否能够生成共享库。但是,它不能推断出对于它不知道的编译器需要什么编译器标志,因此您必须提供它们。您需要在命令行上提供必要的标志(例如通过CFLAGS=-fPIC)。 - Dan Moulding
3
这只是一个辅助的警示而不是回答。在上述情况中将gcc作为cc来调用不会使其操作有所不同,但调用软件的操作方式不直观,导致出现了不同的行为。 - ednos

3
这篇帖子可能有些陈旧,但我想要补充一些内容(或许将来会有人发现它)。
如果你编译了这个程序...
#include <stdio.h>
#include <stdlib.h>

void
myFunction(char *args)
{
   char buff1[12];
   char buff2[4] = "ABC";

   strcpy(buff1,args);

   printf("Inhalt Buffer2: %s",buff2);

}

int main(int argc, char *argv[])
{

   if(argc > 1)
   {
      myFunction(argv[1]);
   }
   else
      printf("no arguments sir daimler benz");

   getchar();

   return 0;
}

如果您使用“gcc”编译,并将“AAAAAAAAAAAAAAAAAAAAAAAAA”作为参数传递,它不会溢出到buffer2,而如果您使用“cc”编译,则会溢出到buffer2。这对我来说是一个提示,如果您使用“gcc”,内存管理工作方式不同,也许通过在字段buff1和buff2的内存段之间放置空间来实现?也许有更多经验的人可以给我们带来启示。

1
我尝试了这个(在gcc版本4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)上),关闭和开启堆栈保护都以段错误检测到堆栈破坏结束,最后cc链接到/etc/alternatives/cc,它又链接到/usr/bin/gcc。正如@abcoep所说,cc和gcc只有在制表符补全方面不同(就我所调查的)。 - Kyslik

3

cc是UNIX调用编译器的方式,可以在所有的Unix系统上使用。


2
这并没有回答问题。 - bortzmeyer
3
实际上,它确实有意义。在Unix中,cc代表“C编译器”,没有其他含义。 - ismail
1
提问者也询问了cc和gcc的区别。在我看来,这也是一个回答,回答了这个问题。 - Johannes Schaub - litb

2

“无论是通过'gcc'还是'cc'调用,GCC的行为都是相同的。”

[引自原始帖子。]

根据我的经验,在Ubuntu 14.04中并非如此。

当我使用以下命令编译我的程序时:

gcc -finstrument-functions test.c

我的代码没有任何变化。但是当我使用编译器编译时

cc -finstrument-functions test.c

它确实有不同的行为。(在这两种情况下,我已经将描述如何使-finstrument-functions工作的适当更改纳入了我的代码中,详见此处)。


2
GCC文档中没有任何迹象表明,如果其可执行文件名不是gcc而是cc,GCC会有任何不同的行为。GNU Fortran编译器甚至提到了这一点:

gcc命令的一个版本(也可能安装为系统的cc命令)


1

对于我的操作系统(Ubuntu 14.04),cc不支持制表符自动完成,而gcc可以。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接