我期望用C++编译器编译C代码有什么问题?

Chr*_*uin 34 c c++ migration compiler-construction language-interoperability

如果您使用现有的C代码库并使用C++编译器进行编译,那么您可能会遇到什么样的问题?例如,我认为将一个整数分配给具有枚举类型的值将在C++中失败,而在C中它是合法的(如果有点讨厌).

如果我没有包装我的所有C文件extern C { ... },我是否会在最不期望的地方获得名称错误?有什么理由我真的不应该这样做吗?

作为背景,我们有一个用C编写的非常大的代码库.几年来,我们一直在跳过箍来做一些自然而然的事情来通过C++(例如homebrewe继承).我们希望开始转向C++,但是要逐步进行; 获得我们类似CORBA的框架来支持它,并在我们继续使用C++提供的更自然的方法时重构模块.

Vil*_*ari 33

我曾经做过类似的事情.问题的主要来源是C++对类型的更严格,正如您所怀疑的那样.你必须添加转换,其中void*与其他类型的指针混合.像分配内存一样:

Foo *foo;
foo = malloc(sizeof(*foo));
Run Code Online (Sandbox Code Playgroud)

以上是典型的C代码,但它需要在C++中使用强制转换:

Foo *foo;
foo = (Foo*)malloc(sizeof(*foo));
Run Code Online (Sandbox Code Playgroud)

C++中有新的保留字,例如"class","and","bool","catch","delete","explicit","mutable","namespace","new","operator", "或","私人","受保护","朋友"等.例如,这些不能用作变量名.

当您使用C++编译器编译旧C代码时,上述可能是最常见的问题.有关不兼容性的完整列表,请参阅ISO C和ISO C++之间的不兼容性.

你也问过名字错误.在没有extern"C"包装器的情况下,C++编译器破坏符号.只要您使用C++编译器,并且不依赖于dlsym()或类似的东西从库中提取符号,这不是问题.

  • 正是出于这个原因,我在伪OO C代码中使用`self`. (4认同)
  • "C++中有新的保留字".我倒下的那个是"这个".当你有一些模糊的OO C代码时,很可能有人用它来表示它在C++中意味着什么...... (2认同)
  • 哎哟! 我忘了这件事.我们有非常OO的代码,在我们的组件结构中有很多"this"的用法.现在,我的一位开发人员会说"我告诉过你",因为他在代码审查期间警告过我,我可能不应该使用"这个". (2认同)

Ada*_*eld 22

ISO C和ISO C++之间的不兼容性一个非常所有不兼容的详细清单.存在许多微妙的问题,包括一些不会立即在编译器错误中出现的问题.例如,一个可能存在问题的问题是字符常量的大小:

// In C, prints 4.  In C++, prints 1
printf("%d\n", sizeof('A'));
Run Code Online (Sandbox Code Playgroud)


Ste*_*sop 8

如果我没有将所有的C文件包装在"extern C {...}"中,我是否会在最不期望的地方获得名称错误?

当您尝试将C和C++链接在一起时,它会咬你.

我写了很多包含以下内容的头文件:

#ifdef __cplusplus
    extern "C" {
#endif

// rest of file

#ifdef __cplusplus
    }
#endif
Run Code Online (Sandbox Code Playgroud)

过了一会儿,它会合并到现有的多包含样板文件中,你就会停止看到它.但你必须要小心你把它放在哪里 - 通常它属于任何包括你的标题之后.

有什么理由我真的不应该这样做吗?

如果你确定你不会将C和C++结合起来那么我就没理由这样做了.但是,随着您描述的渐进式迁移,对于具有已发布接口的任何内容都必须使用C组件和C++组件.

这样做的重要原因是它会阻止你重载函数(至少在那些头文件中).将所有代码迁移到C++并开始维护/重构/扩展它之后,您可能会发现要这样做.


Gra*_*her 5

一般来说,您根本不会遇到任何问题。是的,C 和 C++ 之间存在一些不兼容性,但除了上面提到的 malloc 转换之外,它们似乎并不经常出现,修复起来非常简单。

我已成功编译并使用以下开源 C 库作为 C++:

  • Expat XML 解析器
  • FreeType2 字体光栅化器
  • libjpeg:处理 JPEG 图像
  • libpng:处理 PNG 图像
  • Zlib 压缩库

最困难的部分是添加命名空间包装器,这花了几个小时,主要是因为 #include 语句深埋在代码中,而这些语句必须位于 C++ 命名空间之外。

我为什么要这样做?因为我出售一个商业图书馆,人们可以直接链接到他们的应用程序;有时他们的应用程序会链接到其他版本的 Expat、FreeType 等。这会导致多重定义符号错误。最干净的做法是将所有内容移至我的库中并将其隐藏在我的命名空间中。

然而,我并没有对我使用的所有开源库都这样做。有些还没有引起冲突,我也没有时间去解决它们,虽然没有麻烦,但相当乏味。有趣的例外是 SQLite,我无法用 C++ 对其进行编译。因此,我进行了大量搜索和替换,为每个外部可见的符号添加了前缀(我的产品名称)。这解决了我客户的问题。