【问题标题】:what is the main reason not to compile c code with g++? [closed]不使用 g++ 编译 c 代码的主要原因是什么? [关闭]
【发布时间】:2025-11-22 07:30:01
【问题描述】:

首先,不好意思问了这么奇怪的问题

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

我做了一些搜索,我得到了:“它们是两种非常不同的语言”、“不要这样做”等,但我从未找到详细的解释

为什么?有推荐的文章吗?

【问题讨论】:

  • 对我来说,这个问题听起来像是“不使用 javac 编译 C# 的主要原因是什么?”
  • 我知道这是一个愚蠢的问题,但我真的不明白。当我使用g++编译一些c代码时,它仍然可以正常运行,为什么?
  • C 和 C++ 中用于解决编程问题的工具大不相同。如果您不需要使用 C,最好使用 C++ 以获得长期利益。
  • 也许你会觉得这很有趣:*.com/questions/12887700/…
  • int new = 42;,这就是为什么:-)

标签: c++ c compilation


【解决方案1】:

对于您的一般问题,没有简单的答案。 C++ 仅支持 C 的 子集。如果您想编写有效的代码并且 在两种语言中具有相同的语义,那么您将受到很大限制。一些不是有效 C++ 的 C 代码示例如下:

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

  • C 已经指定了结构和数组初始化器,它们在典型的 C 项目中通常是一个好主意。你可以写例如

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

    这不是有效的 C++。

  • 在 C 中,你必须写 struct foo 来引用带有 tag foo 的结构,而 C++ 允许只写 foo。对于typedefs,这会产生一个奇怪的后果。在 C 中,你可以有

    struct foo;
    typedef struct bar foo;
    

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

  • 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
}

ma​​in.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

【讨论】:

  • 好答案,但我害怕OP需要;我理解他想从实际的 C 代码中调用 C++ 代码,这不是完全相同的问题。
  • 最后一段应该清楚如何设计这个。不过,一个例子会很大......也许我稍后会添加一个,现在必须去。
  • 并非如此,因为从 C 代码调用 C++ 需要的不仅仅是使用 extern "C",因此应该构建一些包装。
  • @Jean-BaptisteYunès 好吧,我添加了一个最小的例子(不幸的是仍然很大),也许它有助于理解我在说什么。
  • 拆分成多个翻译单元是要走的路,+1。
【解决方案2】:

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

无需将printf() 替换为cout。但同时也不是“用 C++ 编译器编译 C 代码”那么简单。

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

如果幸运的话,启用所有警告的 C++ 编译器会突出显示 C 代码中任何有问题的部分。如果运气不好,可能需要更新一小部分 C 代码才能使用 C++ 编译器进行编译并正常运行。

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

【讨论】:

    【解决方案3】:

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

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

    C++ 编译器会产生关于这些的错误,所以如果你有耐心的话,这些错误并不难找到和修复。

    一些差异在两种语言中可能有效,但行为不同。这种情况更难被发现。一些示例显示在:

    【讨论】:

      【解决方案4】:

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

      • gcc: cc1 for C
      • g++:用于 C++ 的 cc1plus

      您可以使用-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++ 链接它在标准 C++ 库中自动链接的目标文件(gcc 不这样做)。 g++ 还有额外的宏。

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

      【讨论】:

        【解决方案5】:

        c++ 语言向后兼容所有 c 代码,因为它是 c 语言的继承者。这就是为什么您的 c 代码仍然可以使用 g++ 编译的主要原因。但是为了良好的编程习惯,如果你在 g++ 上编译,请用 c++ 编写代码,因为问题确实存在。

        【讨论】:

        • 这是矛盾的。 “问题确实存在” vs “向后兼容所有 c 代码”(反正前者不正确,C++ 缺少 VLA 和指定的初始化程序)。
        最近更新 更多