C 和 C++ 编码标准

发布于 2024-07-09 06:36:12 字数 278 浏览 4 评论 0原文

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

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

What are best practices with regards to C and C++ coding standards? Should developers be allowed to willy-nilly mix them together. Are there any complications when linking C and C++ object files.

Should things like socket libraries that traditionally is written in C remain in C and kept in seperate source files? That is keeping c code in .c files and c++ code in .cpp files.
When mixing c and C++ after being parsed with g++ will there be any performance penalties, since typesafe checks are not done in C? but are in C++. Would would be the best way to link C and C++ source code files.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

瑾夏年华 2024-07-16 06:36:12

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

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

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

#if defined( __cplusplus )
}
#endif

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

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

extern "C" {
#include "myfuncheader.h"
}

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

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

The biggest issue is calling a C function from C++ code or vice versa. In that case, you want to make sure you mark the function as having "C" linkage using extern "C". You can do this in the header file directly using:

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

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

#if defined( __cplusplus )
}
#endif

You need the #ifs because C code that includes it won't understand extern "C".

If you don't want to (or can't) change the header file, you can do it in the C++ code:

extern "C" {
#include "myfuncheader.h"
}

You can mark a C++ function as having C linkage the same way, and then you can call it from C code. You can't do this for overloaded functions or C++ classes.

Other than that, there should be no problem mixing C and C++. We have a number of decades-old C functions that are still being used by our C++ code.

暖风昔人 2024-07-16 06:36:12

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

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

C++ doesn't do 'typesafe checks' at run time unless you ask for them (by using dynamic_cast). C++ is highly compatible with C, so you may freely call C libraries as you wish and compile C code with a C++ compiler. C++ does not imply 'object-oriented', and you should get no performance penalty from using it.

If you mix code compiled with gcc and with g++, see Graeme's answer.

黑寡妇 2024-07-16 06:36:12

人们通常应该假设 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;
    }
}

One should generally assume that c++ can throw exceptions, hence the c wrapper functions in your block, ought to catch them, and morph them into nice error codes that the c caller can digest.

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;
    }
}
守望孤独 2024-07-16 06:36:12

如果 C++ 中有一个函数,它调用 C 中的一个函数,而该函数又调用 C++ 中的另一个函数,并且后面的函数抛出了一个应该由第一个函数捕获的异常,那么除非您告诉 C 编译器启用异常处理表的生成。

对于 gcc,这是 - fExceptions 参数,对于 C++ 默认启用,但对于 C 默认禁用。

If you have a function in C++ which calls a function in C which in turn calls another function in C++, and this later function throws an exception which should be caught by the first function, you can have problems unless you told the C compiler to enable generation of the exception handling tables.

For gcc, this is the -fexceptions parameter, which is enabled by default for C++ but disabled by default for C.

Smile简单爱 2024-07-16 06:36:12

这里没有好的硬性规定。

如果最终产品总是与 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 ); }
 };

我希望这会有所帮助。

There are no good hard and fast rules here.

If the end product will always be linked with a C++ main() then it does not really matter. As you can always create headers that will do the correct thing.

If you are creating a library that needs to have a C and C++ interface but you can't assume the C++ linker then you will need to make sure you separated the C API from the C++ cleanly. At this point it is usually cleaner to do all the work in C and use C++ classes to proxy to the C.

For example:

/* 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 ); }
 };

I hope this helps.

眉黛浅 2024-07-16 06:36:12

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

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

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

If you compile all your source with g++ then it is all compiled in C++ object files (i.e. with the appropriate name mangling and the C++ ABI).

You will only need to use the extern "C" trick if you are building libraries that need to be used by explicitly C applications that need to use the C ABI.

If everything is being compiled into a single executable then use g++ and treat everything as C++

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文