代码之家  ›  专栏  ›  技术社区  ›  Chris Arguin

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

  •  31
  • Chris Arguin  · 技术社区  · 16 年前

    如果你使用一个现存的C代码库并用C++编译器编译它,你能想出什么样的问题?例如,我认为将一个整数赋给具有枚举类型的值将在C++中失败,而在C.则是合法的(如果有点讨厌)。

    如果我不把所有的C文件都包装在 extern C { ... } ,我会把名字弄到我最不期待的地方吗?我真的不应该这样做有什么原因吗?

    对于背景,我们在C中有一个非常大的代码库。几年来,我们一直在跳转,通过C++来实现自然的事情(例如,HOBBRWE继承)。我们希望开始向C++移动,但以渐进的方式;让我们的CORBA类框架来支持它,以及重构模块,以便我们利用C++提供的更自然的方法。

    8 回复  |  直到 8 年前
        1
  •  32
  •   Ville Laurikari    16 年前

    我做过类似的事。问题的主要来源是C++对类型的要求更严格,正如你所怀疑的。您必须添加void*与其他类型的指针混合的强制转换。比如分配内存:

    Foo *foo;
    foo = malloc(sizeof(*foo));
    

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

    Foo *foo;
    foo = (Foo*)malloc(sizeof(*foo));
    

    C++中有新的保留词,如“类”、“和”、“布尔”、“catch”、“删除”、“显式”、“可变”、“命名空间”、“新”、“运算符”、“或”、“私有”、“保护”、“朋友”等。这些变量不能用作变量名。

    上述问题可能是用C++编译器编译旧C代码时最常见的问题。有关不兼容的完整列表,请参阅 Incompatibilities Between ISO C and ISO C++ .

    你也会问起名字曼格林。在没有外部“C”包装的情况下,C++编译器 把符号弄乱。只要你用就没问题了 只有 一个C++编译器,不依赖于DLScript()或类似的东西来从库中提取符号。

        2
  •  19
  •   Adam Rosenfield    16 年前

    Incompatibilities between ISO C and ISO C++ 对于一个 非常 所有不兼容的详细列表。有很多微妙的问题,包括一些不会在编译器错误中立即出现的问题。例如,有一个问题可能是字符常量的大小:

    // In C, prints 4.  In C++, prints 1
    printf("%d\n", sizeof('A'));
    
        3
  •  7
  •   Steve Jessop    16 年前

    如果我不把所有的C文件都包装在“外部C”中…}“,我要把名字弄到我最不期待的地方吗?

    当你试图连接C和C++时,它会咬你。

    我写了很多头文件,其中包括:

    #ifdef __cplusplus
        extern "C" {
    #endif
    
    // rest of file
    
    #ifdef __cplusplus
        }
    #endif
    

    过了一会儿,它合并到现有的multiple-include样板文件中,您就看不到它了。但是你必须小心放在哪里-通常它是属于你的 之后 任何包括你的标题。

    我真的不应该这样做有什么原因吗?

    如果你确信你不会把C和C++结合起来,那么我就没有理由这么做了。但是,随着您描述的逐步迁移,对于具有C接口和C++组件都需要使用的已发布接口的任何东西都是必不可少的。

    最大的原因 这样做是为了防止函数过载(至少在这些头中)。您可能会发现,一旦您将所有代码迁移到C++并开始维护/重构/扩展它,您就希望这样做。

        4
  •  2
  •   piotr    16 年前

    另一个例子:C++中没有从int到隐式的隐式转换,在C.有一个,如果你真的想用C++来做的话,你需要一个强制转换。

        5
  •  1
  •   paulm    11 年前

    在使用msvc之前,我已经完成了这项工作,如果使用msvc,一个好的策略是:

    1. 将各个文件设置为构建为cpp,这样您就可以增量地移动到cpp编译器。
    2. 使用ctrl+f7逐个文件地工作,只需构建一个文件。
    3. 您可以创建一个模板版本,而不是强制执行所有malloc。

    foo=(foo*)malloc(sizeof(*foo));

    变成

    foo = malloc<Foo>();
    

    当然,对于需要foo+n字节的情况,可以有一个重载

    我还建议在可能的情况下将内存分配切换到使用raii,我发现有些功能非常复杂,因此切换到raii的风险太高,对于大多数情况来说,这已经足够简单了。

        6
  •  1
  •   Graham Asher    9 年前

    一般来说,你不会遇到任何问题。是的,C和C++之间有一些不兼容,但是除了上面提到的Maloc铸件,它们似乎并没有出现,这是很难修复的。

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

    • expat XML解析器
    • freetype2字体光栅器
    • libjpeg:处理jpeg图像
    • libpng:处理png图像
    • zlib压缩库

    最难的部分是添加命名空间包装器,这花费了几个小时,很大程度上是因为隐藏在代码中的“包含”语句必须位于C++命名空间之外。

    我为什么要这么做?因为我卖了一个商业图书馆,人们直接链接到他们的应用程序;有时他们的应用程序链接到其他版本的expat、freetype等,这导致了多重定义的符号错误。要做的最干净的事情是将库中的所有内容都移动并隐藏在我的名称空间中。

    但是,我并没有用我使用的所有开源库来实现这一点。有些人还没有引起冲突,我也没有时间去解决它们,尽管没有麻烦是相当乏味的。有趣的例外是SQLite,这是我无法在C++中编译的。所以我进行了大量的搜索和替换,在每个外部可见的符号上添加了一个前缀(我产品的名称)。这解决了我客户的问题。

        7
  •  0
  •   Stack Exchange Supports Israel    16 年前

    C++有更严格的类型检查,所以您可能需要向每个调用MalC/ReAlcC/CaloC添加一个强制转换。

        8
  •  -2
  •   Dimitrie D.    9 年前

    尝试用C++编译器编译:

    typedef enum{ false = 0, true = 1} bool;
    
    推荐文章