1

我有一些为 C99 程序编写的头文件。此标头包含所有函数定义,并且不与源文件配对。我将它包含在 C++ 文件中。

我的 C++ 编译器标志 include -pedantic -std=c++11,它在头文件中给了我各种警告,例如“ISO C++ 禁止复合文字”和“ISO C++ 禁止可变长度数组”。显然,C++ 编译器将 C99 代码视为 C++。两个问题:

  1. 在尝试编写可以在使用不同编译器的各种平台上正确运行的代码时,这是一个潜在的问题吗?
  2. 解决警告并生成符合标准的代码的好方法是什么?我正在考虑使用 gcc 制作一个预编译的头文件,但对该过程知之甚少,无法确保我不会因为在 C++ 源代码中包含 C 预编译头文件而产生意外后果。

谢谢

4

2 回答 2

5

在尝试编写可以在使用不同编译器的各种平台上正确运行的代码时,这是一个潜在的问题吗?

是的。GCC 可能只是给出警告,其他编译器(例如 Visual Studio 或带有其他选项的 GCC)很可能会给出错误。

解决警告并生成符合标准的代码的好方法是什么?

解决问题的正确方法是在 C 和 C++ 的公共子集中编写标头。使用 C99 特性(例如可变长度数组和复合文字)的函数和对象定义应移至单独的 C 源文件(使用 C 编译器编译!)。

于 2013-01-19T19:36:06.077 回答
4

要在 C++ 项目中包含纯 C 头文件 (*),您应该将 include 语句包装在一个extern "C"块中:

// C++
extern "C" {
// C-code goes here
#include "foo.h"
}

这是因为 C++ 对所有函数名执行名称修改以使重载工作。C 不使用名称修饰,因此 C++ 使用名称修饰解析 C 函数签名

请注意,extern "C"它不会将编译器置于“C 模式”(没有这种模式,但您可能会错误地认为该指令是这样的),它不会破坏函数名称(+ 更改调用约定并禁止重载; 感谢末日论者指出这些事情)。

但是,如果您只包含头文件(使用内联实现),这应该不是问题,因为只有当您将 C 源文件或库链接到 C++ 项目时,此名称修改才会成为问题,因为函数名称是在这种情况下不同。

话虽如此,您应该使用C 和 C++的公共子集作为头文件,使用 C 编译器而不是 C++ 分别提取和编译这些函数的实现。然后,您(希望)可以将这两个部分链接在一起。很多 C 库已经有与 C++ 兼容的头文件,所以这是一个常见的过程。

(*):通过使用语言功能的公共子集以及将所有内容包装在条件 extern "C"块中,一些头文件已经与 C 和 C++ 语言兼容。对于此类标头,您不应使用此方法,而仅适用于其中没有此类块的标头。

于 2013-01-19T19:48:59.600 回答