galagala galagala - 1 month ago 11
C Question

what is the main reason not to compile c code with g++?

first, sorry for ask such a weird question

I used c in a project, and after some study, I found better method with some c++ libraries, but I really don't want to rewrite the code( say, printf to cout).

I did some search, and I got : "they are two very different language", "DON'T DO IT", etc. but I never found a detailed explanation

why? are there some recommended articles to read?

Answer Source

To your generic question, there's no simple answer. C++ only supports a subset of C. If you want to write code that's valid and has the same sematics in both languages, you're very limited. Some examples of C code that's not valid C++ are:

  • Code that uses keywords of C++ that don't have a special meaning in C like class, this, new etc. To avoid confusion, you normally try to avoid these keywords in C, but it's of course not necessary.

  • C has designated struct and array initializers and they are often a good idea in a typical C project. You could write for example

    struct foo {int a; char b; short c; };
    struct foo x = { .b = 'x', .c = 42 };
    

    this isn't valid C++.

  • In C, you must write struct foo to refer to a structure with tag foo, while C++ allows to just write foo. This has a strange consequence when it comes to typedefs. In C, you could have

    struct foo;
    typedef struct bar foo;
    

    This is just an example, the code is confusing of course. But it's invalid code in C++, because it would be unclear what you refer to when just writing foo. Therefore, in C++, a typedef with the same name as a struct tag must refer to the exact same type.

  • C supports flexible array members as the last element of a struct like this:

    struct foo { int x; int a[]; }
    

    The size of a is determined when you allocate memory for that struct (adding n * sizeof(int)). This feature doesn't exist in C++

  • In C, pointer casts are almost always wrong, while they can be used in C++ for casting between a base class and a derived one. Therefore, C has the concept of a generic pointer void * that can be converted without a cast. In C++, converting to and from void * requires a cast like with any other pointer type.

These are just the examples that I could think of immediately, there are probably more. So yes, it's never a good idea to compile C code with a C++ compiler.


I used c in a project, and after some study, I found better method with some c++ libraries, but I really don't want to rewrite the code

For this problem, there's another simple solution. Divide your code into multiple translation units. There's no problem at all with a mixed C/C++ project, as long as the C and C++ source files are distinct.

So that means you factor out all the code using your C++ library in a C++ file and compile only that file with a C++ compiler. For the public interface of that C++ module, use extern "C" declarations and guard them with an #ifdef __cplusplus to hide them from the C compiler.

The structure could look like this (very simplified), if the part using C++ is in a translation unit called module here:

module.h:

#ifndef MODULE_H
#define MODULE_H

#ifdef __cplusplus
// the C++ compiler will see this causing all declarations in the block to have C linkage,
// the C compiler won't see it (skipped by the preprocessor)
extern "C" {
#endif

int module_foo(int arg);

#ifdef __cplusplus
}
#endif

#endif

module.cpp:

#include "module.h"
#include <mycpplib> // example

int module_foo(int arg)
{
    // some C++ code using your C++ library
}

main.c:

#include "module.h"

int main(void)
{
     int x = module_foo(42);
}

You could build a complete program like this:

gcc -c -omain.o main.c
g++ -c -omodule.o module.cpp

# link them together, using the C++ library libmycpplib:
g++ -oprogram main.o module.o -lmycpplib