【问题标题】:Standard C++ way of calling C standard library functions调用 C 标准库函数的标准 C++ 方式
【发布时间】:2019-01-16 08:37:12
【问题描述】:

我有几个关于在 C++ 中调用 C 标准库函数的问题:

  1. 如果我想调用在<stdio.h> 中声明的getline(),是否只包含<cstdio> 就足够了?这适用于我正在使用的编译器,我看到它在 <cstdio> 中包含 <stdio.h>,但我想知道标准是否保证这一点。
  2. 是否所有 C 标准库函数都保证在 C++ 中可用?在上面的getline() 示例中,我注意到在cppreference<cstdio> 下它没有列出getline()
  3. 对于在 std:: 命名空间中可用的 C 标准库函数和类型,如 FILEmalloc(),它们在通过全局命名空间访问它们时是否有任何问题,或者将它们作为 @ 访问它们是否更习惯987654334@或std::malloc()

【问题讨论】:

  • getline 不是 C 标准库函数,它是 POSIX。如果它在您的编译器的 C 库中可用,则它在 C++ 中可用。
  • 假设它是您正在考虑的POSIX getline function,不能保证<cstdio> 会声明它。它可能会,但不能保证,因为它不是标准 C++ 或标准 C 的一部分。
  • 你们是对的,我错过了它是一个 POSIX 函数,它回答了我上面的第 2 个问题。

标签: c++ c++11 c++-standard-library


【解决方案1】:

您应该始终包含文档告诉您的内容。 (通常会编写 C++ 标准库实现,以便可以通过其他包含访问函数,但当然依赖这意味着您的代码不可移植。)请注意,C 中没有 标准 getline 函数. 但是C++中有一个:

std::getline()

在标题<string> 中定义。 C++ 标准通常不保证 C 函数在全局范围内可用,甚至是 C++ 标准库的一部分。这两种语言在多年前就开始出现分歧,因此 C++ 在某种意义上是 C(包括库)的超集的想法是一个神话。

参考:https://en.cppreference.com/w/cpp/string/basic_string/getline

【讨论】:

  • 事实证明我指的是 POSIX getline(),正如@molbdnilo 指出的那样。关于你的最后一点,我读过这个previous answer,这似乎表明如果你包含像stdio.h 这样的C 头文件,C++ 标准确实保证C 函数在全局范围内可用。
【解决方案2】:

关于#3

.h 库必须将其所有名称放在全局命名空间中,也可以将它们放在 std:: 命名空间中。

c 起始版本必须将其所有名称放在 std:: 命名空间中,也可以将它们放置在全局命名空间中。

【讨论】:

  • 这是我在之前链接的答案中读到的内容,但@bathsheba 似乎说相反:C++ 标准通常不保证 C 函数在全局范围内可用
【解决方案3】:

一般来说,将任何 C 库与 C++ 链接应该很容易,而不仅仅是标准头文件。

请注意,您可能需要通过 man 搜索来确定该方法是哪个版本的 unix 引入的,或者它是否是一个特定的扩展,并自行决定您是否可以接受该历史起点。但是,如果您编写的是 C 程序而不是 C++,则情况确实如此。

C++ 别名标头包含 C 标头中的大部分功能,但不是全部功能,但有时您可能会发现获取函数的唯一方法是直接包含 C 标头。另一方面,您需要问自己为什么他们选择不包含该方法,通常是因为它已被弃用、危险或不标准。

所以它的工作方式是使用 extern "C" 关键字引入 C 函数,包括 C 库函数。

当你#include C 头文件时,它们通常会包含一些代码,例如:

/* C++ needs to know that types and declarations are C, not C++.  */
#ifdef  __cplusplus
# define __BEGIN_DECLS  extern "C" {
# define __END_DECLS    }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif

__BEGIN_DECLS

...其中介绍了一段C接口函数。

如果您需要包含一个没有这样做的非常旧的 C 库,那么您可以轻松地在 #include 周围添加extern "C"

extern "C" {
#include "ancientinterface.h"
};

您还可以编写自己的与“C”接口兼容的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 2017-10-08
    • 1970-01-01
    • 2011-06-16
    • 2015-10-08
    • 2016-02-16
    • 2017-08-03
    相关资源
    最近更新 更多