C 和 C++ 编码标准

Posted

技术标签:

【中文标题】C 和 C++ 编码标准【英文标题】:C And C++ Coding Standards 【发布时间】:2008-11-12 11:48:05 【问题描述】:

关于 的最佳实践是什么?是否应允许开发人员随意将它们混合在一起。链接 C 和 C++ 目标文件时是否有任何复杂情况。

传统上用 C 编写的套接字库之类的东西是否应该保留在 C 中并保存在单独的源文件中?就是将 c 代码保存在 .c 文件中,将 c++ 代码保存在 .cpp 文件中。 在用 g++ 解析后混合 c 和 C++ 时会不会有任何性能损失,因为 C 中没有进行类型安全检查?但在 C++ 中。将是链接 C 和 C++ 源代码文件的最佳方式。

【问题讨论】:

【参考方案1】:

最大的问题是从 C++ 代码调用 C 函数,反之亦然。在这种情况下,您要确保使用extern "C" 将函数标记为具有“C”链接。您可以直接在头文件中使用:

#if defined( __cplusplus )
extern "C" 
#endif

extern int myfunc( const char *param, int another_one );

#if defined( __cplusplus )

#endif

您需要 #ifs,因为包含它的 C 代码无法理解 extern "C"

如果您不想(或不能)更改头文件,可以在 C++ 代码中进行:

extern "C" 
#include "myfuncheader.h"

您可以以相同的方式将 C++ 函数标记为具有 C 链接,然后您可以从 C 代码中调用它。您不能对重载函数或 C++ 类执行此操作。

除此之外,混合 C 和 C++ 应该没有问题。我们有许多几十年前的 C 函数仍在我们的 C++ 代码中使用。

【讨论】:

【参考方案2】:

C++ 不会在运行时进行“类型安全检查”,除非您提出要求(通过使用 dynamic_cast)。 C++ 与 C 高度兼容,因此您可以随意调用 C 库并使用 C++ 编译器编译 C 代码。 C++ 并不意味着“面向对象”,您应该不会因为使用它而受到性能损失。

如果您混合使用 gcc 和 g++ 编译的代码,请参阅 Graeme 的回答。

【讨论】:

只是一个细节,但 C++ 编译器将使用内置 C 编译器编译 C。 C 与 C++ 有一些不同之处。 哦,是的。不过,我认为 OP 将结构化的、调用函数样式的代码称为“C 代码”,而我的观点是这种样式也是“C++ 代码”;因为使用 C++ 没有任何惩罚,所以最好不要担心差异并用 C++ 做所有事情(不一定是 OOP!)。【参考方案3】:

人们通常应该假设 c++ 可以抛出异常,因此块中的 c 包装函数应该捕获它们,并将它们转化为 c 调用者可以消化的漂亮错误代码。

extern "c"

    int nice_c_function_interface
    (
        void
    )
    
        int returnStatus;

        try
        
             returnStatus = nice_cpp_function();
        
        catch (NiceCppException& that)
        
             returnStatus = that.failure_code();  
        
        catch (...)
        
            cerr << "Oh Worse! an unexpected unknown exception" << endl;

            returnStatus = -1;  // Horrible unknown failure
        

        return returnStatus;
    

【讨论】:

【参考方案4】:

如果你有一个 C++ 中的函数调用 C 中的一个函数,而该函数又调用 C++ 中的另一个函数,而这个后面的函数抛出一个应该被第一个函数捕获的异常,你可能会遇到问题,除非你告诉 C编译器以启用异常处理表的生成。

对于gcc,这是-fexceptions参数,C++默认开启,C默认关闭。

【讨论】:

【参考方案5】:

这里没有好的硬性规定。

如果最终产品总是与 C++ main() 链接,那么这并不重要。因为您始终可以创建能够执行正确操作的标头。

如果您正在创建一个需要具有 C 和 C++ 接口但您不能假定 C++ 链接器的库,那么您需要确保将 C API 与 C++ 完全分离。此时,在 C 中完成所有工作并使用 C++ 类代理到 C 通常更简洁。

例如:

/* c header */

struct CData
  /* stuff */ ;

void init( CData* data );
void fini( CData* data );
int getSomething( CData* data );
void doSomething( CData* data, int val );

// c++ header

extern "C" 
#include cdata.h
;

class CppData : private CData
 
 public:
   CppData()  ::init( (CData*)this ); 
   ~CppData()  ::fini( (CData*)this ); 
   int getSomething()  return ::getSomething( (CData*)this ); 
   void doSomething( int val )  :: doSomething( (CData*)this, val ); 
 ;

我希望这会有所帮助。

【讨论】:

【参考方案6】:

如果您使用 g++ 编译所有源代码,那么所有源代码都会在 C++ 目标文件中编译(即使用适当的名称修饰和 C++ ABI)。

如果您正在构建需要由需要使用 C ABI 的显式 C 应用程序使用的库,则只需使用 extern "C" 技巧。

如果所有内容都被编译为单个可执行文件,则使用 g++ 并将所有内容视为 C++

【讨论】:

以上是关于C 和 C++ 编码标准的主要内容,如果未能解决你的问题,请参考以下文章

纯C(非C ++)的编码标准

WChars、编码、标准和可移植性

为啥使用非标准 C(gcc 特定功能)对 linux 内核进行编码? [关闭]

读C#代码整洁之道笔记01_C#的编码标准和原则

Go语言标准包之json编码

请问如何用C语言实现汉字,和Unicode编码的转换?