GCC编译无效的C代码

3

我的一些C程序没有按预期工作。例如,在C中不可能使用传递引用的方式,但是当我编写一个使用该方法并使用gcc编译的C程序时,它却可以正常工作。

gcc是一个C++编译器吗?我该如何使其像C编译器一样运行?


11
没有代码,你不能这么说(关于PBR)! - Joe
2
我同意Joe的观点:你需要发布你的代码 - 包括文件名。如果你的源文件扩展名为 .cpp、.cc、.C 或 .c++(或其他一些),它将被编译为 C++。如果使用 gcc(或g++)编译 .c 文件,则引用调用将*不会 *被编译。另请注意,如果你尝试使用 gcc 链接 c++ 对象,它可能无法成功链接,因为gcc不会默认链接 C++ 库。 - Tim Schaeffer
gcc会查看文件扩展名。如果文件是*.c,则编译为C语言。如果文件是*.cpp,则编译为C++语言。 - Martin York
@Roger 我的意思是“引用传递”。 - Joe
6个回答

10

gcc,g++ 和其他前端使用文件名来确定语言。例如,gcc 和 g++ 之间唯一的主要区别是针对新 C++ 程序员的一个问题:不同的链接设置(用于 C++ stdlib)。

如果您的文件被错误地检测,请使用 -x 选项(和可能的 -std)进行显式指定。或者遵循 gcc 用于文件名的通用命名约定。对于 C 语言,这意味着 *.c。

仔细检查您是否使用大写的 *.C 命名您的文件;这将被检测为 C++。


7
如果我编译这个代码:
int f( int & r ) {
    return r + 1;
}

int main() {
    int x = 3;
    return f( x );
}

使用:

 gcc e.c

我得到:

 e.c:1: error: expected ';', ',' or ')' before '&' token

你是否给你要编译的文件加上了 .cpp 扩展名?如果是,gcc驱动程序将把它编译为C++文件。


5

程序gcc是一个驱动程序,它可以根据安装的编译器和文件扩展名分配到C、C++、Ada、Fortran、Java和可能其他编译器。

如果这些选择得当,你不需要做任何事情就可以将C文件编译为C,将C++文件编译为C++。要强制编译为C,请在编译文件之前使用选项-x c

我猜测你将文件命名为大写C而不是小写C,因此大写C被认为是C++。


4
尝试定义命令行选项-pedantic,并指定您希望遵循的C标准,例如对于C99,使用--std=c99,对于C89,使用--std=c89;这应该使其拒绝任何不属于指定标准的内容。
编辑:请注意,-ansi可以表示C89或C++98,并且可能无法强制编译器进入“C模式”。

实际上,如果它认为文件是C++源代码,则会忽略像--std=c89这样的标志。但是它会警告您正在这样做。 - anon
如果文件已经具有扩展名.cpp,则指定C标准会导致警告。不过,尝试这样做表明其他地方出现了问题。=) - Arkku
所以看起来这个解决方案只适用于带有-Werror(停止make等)的特定问题。是否应该始终使用该选项是另一个问题。(提示:是的:P) - Roger Pate

2

gcc 是驱动程序。它将根据文件扩展名或强制使用 -x 调用实际的不同前端。

但是对于 g++,默认情况下会强制将源文件视为 C++,即使您的文件是 (*.c)(小写)。

为什么不进行简单的试验以说服自己:

echo "int main() { } " > test.c

gcc -v -c test.c

[请注意 /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1plus 这一行,它是实际的前端编译器。]
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 -quiet -v test.c -quiet -dumpbase test.c -mtune=generic -auxbase test -version -o /tmp/ccUiF4Qr.s
ignoring nonexistent directory "/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/gcc/i386-redhat-linux/4.1.2/include
 /usr/include
End of search list.
GNU C version 4.1.2 20080704 (Red Hat 4.1.2-46) (i386-redhat-linux)
    compiled by GNU C version 4.1.2 20080704 (Red Hat 4.1.2-46).
GGC heuristics: --param ggc-min-expand=59 --param ggc-min-heapsize=55455
Compiler executable checksum: 435964263b657ac05d988fae7b6714b1
 as -V -Qy -o test.o /tmp/ccUiF4Qr.s
GNU assembler version 2.17.50.0.6-12.el5 (i386-redhat-linux) using BFD version 2.17.50.0.6-12.el5 20061020

=============================

mv test.c test.cpp
gcc -v -c test.cpp

=============================

Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1plus -quiet -v -D_GNU_SOURCE test.cpp -quiet -dumpbase test.cpp -mtune=generic -auxbase test -version -o /tmp/ccUgae0u.s
ignoring nonexistent directory "/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2
 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/i386-redhat-linux
 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/backward
 /usr/local/include
 /usr/lib/gcc/i386-redhat-linux/4.1.2/include
 /usr/include
End of search list.
GNU C++ version 4.1.2 20080704 (Red Hat 4.1.2-46) (i386-redhat-linux)
    compiled by GNU C version 4.1.2 20080704 (Red Hat 4.1.2-46).
GGC heuristics: --param ggc-min-expand=59 --param ggc-min-heapsize=55455
Compiler executable checksum: 2c84476b74368e297382b43d14e53b01
 as -V -Qy -o test.o /tmp/ccUgae0u.s
GNU assembler version 2.17.50.0.6-12.el5 (i386-redhat-linux) using BFD version 2.17.50.0.6-12.el5 20061020

================================

mv test.cpp test.c
g++ -v -c test.c

您将得到与 gcc + test.cpp 相同的结果,这意味着编译为 C++。 cc 是 C 前端,cc1plus 是 C++ 前端。就是这样。

0

g++ 应该是 C++ 的前端,cc 是 C 的前端,但两者都指向 gcc。

如果您想编译符合标准的 C 代码,请使用 gcc -ansi


“-ansi” 指定 C 或 C++ 模式下的 C90 或 C++98。而 “-std” 选项则更加明确。 - greyfade

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