不用g ++编译c代码的主要原因是什么?

时间:2017-08-19 05:32:34

标签: c++ c compilation

首先,抱歉提出这样一个奇怪的问题

我在一个项目中使用了c,经过一些研究,我找到了一些c ++库的更好的方法,但我真的不想重写代码(例如,printf到cout)。

我做了一些搜索,我得到了:"他们是两种截然不同的语言","不做其他事情等等但是我从来没有找到详细的解释

为什么呢?有一些推荐的文章可供阅读吗?

5 个答案:

答案 0 :(得分:7)

对于您的通用问题,没有简单的答案。 C ++只支持C的子集。如果你想在两种语言中编写有效且具有相同的语义的代码,那么你就非常有限。一些无效C ++的C代码示例是:

  • 使用C语言的关键字但在C中没有特殊含义的代码,如classthisnew等。避免混淆,你通常会尝试在C中避免使用这些关键字,但这当然不是必需的。

  • C指定了struct和array初始值设定项,它们在典型的C项目中通常是个好主意。你可以写例如

    struct foo {int a; char b; short c; };
    struct foo x = { .b = 'x', .c = 42 };
    

    这不是有效的C ++。

  • 在C中,您必须编写struct foo来引用具有标记 foo的结构,而C ++只允许编写foo。对typedef来说,这有一个奇怪的结果。在C中,你可以拥有

    struct foo;
    typedef struct bar foo;
    

    这只是一个例子,代码当然令人困惑。但它在C ++中是无效的代码,因为在编写foo时你不清楚你所指的是什么。因此,在C ++中,与typedef标记具有相同名称的struct必须引用完全相同的类型。

  • C支持灵活数组成员作为struct的最后一个元素,如下所示:

    struct foo { int x; int a[]; }
    

    为该结构分配内存(添加a)时确定n * sizeof(int)的大小。 C ++中不存在此功能

  • 在C中,指针强制转换几乎总是错误的,而它们可以在C ++中用于在基类和派生类之间进行转换。因此,C具有通用指针 void *的概念,可以在没有强制转换的情况下进行转换。在C ++中,与void * 之间的转换需要类似于任何其他指针类型的转换。

这些只是我能想到的例子,可能还有更多。所以是的,使用C ++编译器编译C代码永远不是一个好主意。

  

我在一个项目中使用了c,经过一些研究,我找到了一些c ++库的更好的方法,但我真的不想重写代码

对于这个问题,还有另一个简单的解决方案。将您的代码划分为多个翻译单元。只要C和C ++源文件不同,混合C / C ++项目就没有问题。

这意味着您在C ++文件中使用C ++库分解所有代码,并使用C ++编译器仅编译该文件。对于该C ++模块的公共接口,使用extern "C"声明并使用#ifdef __cplusplus保护它们以将它们隐藏在C编译器中。

如果使用C ++的部分位于名为module的翻译单元中,结构可能看起来像这样(非常简化):

<强> 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);
}

您可以构建一个完整的程序:

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

答案 1 :(得分:5)

  

我在一个项目中使用了c,经过一些研究,我找到了一些c ++库的更好的方法,但我真的不想重写代码(例如,printf到cout)。

无需将printf()替换为cout。但同时它并不像#34;使用C ++编译器编译C代码那么简单。&#34;

您需要运行所有测试,质量检查和验证步骤,就像移植到新操作系统一样。这是因为C ++实际上并不是100%向后兼容C代码。有几种方法可以编写C代码,如果用C ++编译器编译就会破坏。

如果您很幸运,启用了所有警告的C ++编译器将突出显示C代码中任何有问题的部分。如果您不那么幸运,可能需要更新C代码的一小部分,以便使用C ++编译器进行编译并正常运行。

试试吧。测试一下。但是不要试图删除printf(),这是一个非常好的功能,并且仍然在C ++中得到支持。

答案 2 :(得分:2)

C ++ 不是 C的严格超集。也就是说,合法的C代码不一定是合法的C ++代码。许多典型的差异在C ++中没有语法上的有效,并且无法编译。例如:

  • 隐含void*T*演员。
  • 使用恰好是C ++关键字的标识符。
  • 大多数功能在C99或更高版本中添加到C中。

C ++编译器会生成有关这些错误的错误,因此如果您有耐心,这些错误并不难找到并修复。

然而,有些差异可能在两种语言中都有效,但表现不同。这种情况更难以发现。一些例子显示在:

答案 3 :(得分:0)

GCC代表 GNU编译器集合,是几种主要编程语言的编译器的集成发行版。这些语言是C,C ++,Objective-C,Objective-C ++,Java,Fortran和Ada等。这意味着它的内部:

  • gcc:cc1 for C
  • g ++:cc1plus for C ++

您可以使用-x选项尝试此操作,详细信息为here。比如说,您要编译*.c个文件或*.cpp个文件,分别使用相应的命令:gcc -xc -lstdc -shared-libgcc (or -static-libgcc)gcc -xc++ -lstdc++ -shared-libgcc (-static-libgcc)

差异在于:

gcc*.c/*.cpp文件分别编译为C和C ++,而g++将编译*.c/*.cpp个文件,但它们都将被视为C ++文件。链接也会类似地发生,即g ++链接它在std C ++库中自动链接的目标文件(gcc不这样做)。 g ++还有其他宏。

因此,您可以使用g ++编译C代码,实际上可以混合使用C和C ++代码。最后,可执行文件大小也可能基于编译器而改变。

答案 4 :(得分:-4)

c ++语言向后兼容所有c代码,因为它是c语言的后继者。这就是为什么你的c代码仍然用g ++编译的主要原因。但是对于良好的编程实践,如果你正在编译g ++,那么用c ++编写你的代码,因为问题可以解决。