15

I used c in a project, and after some study, I found a 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 languages", "DON'T DO IT", etc, but I never found a detailed explanation.

Why? Are there some recommended articles to read?

user438383
  • 5,716
  • 8
  • 28
  • 43
galagala
  • 179
  • 1
  • 1
  • 7
  • To me this questions sounds like "what is the main reason not to compile C# with javac?" – Vivick Aug 19 '17 at 05:38
  • I know it's a stupid question, but I just really don't get it. when I use g++ to compile some c code, it still works and execute normally, why? – galagala Aug 19 '17 at 05:41
  • 1
    The tools available in C and C++ to solve programming problems are vastly different. If you are not required to use C, it will be better to use C++ for long term benefit. – R Sahu Aug 19 '17 at 05:41
  • The fact that you are able to compile C code via g++ is tied to the fact that C and C++ share a common basis (therefore any C code using only the common basis is also valid C++ code) – Vivick Aug 19 '17 at 05:43
  • so, if I do pay attention to the c++ rules( say, type casting when using malloc), and not to use the feature that c++ don't support, it's actually OK to do that? – galagala Aug 19 '17 at 05:51
  • Rather look for an explanation, look at the differences in ideologies. [Start with RAII](http://en.cppreference.com/w/cpp/language/raii). Look at the family of problems it solves. Then start looking further abroad. – user4581301 Aug 19 '17 at 05:58
  • If the C++ libraries are better, then use C++. I don't like the C++ libraries myself. They're much harder to version because of the tight binding against certain version of classes. – Antti Haapala -- Слава Україні Aug 19 '17 at 06:12
  • user4581301, that is interesting, thanks for the information : ) – galagala Aug 19 '17 at 06:14
  • 1
    Maybe you'll find this interesting: https://stackoverflow.com/questions/12887700/can-code-that-is-valid-in-both-c-and-c-produce-different-behavior-when-compile – Support Ukraine Aug 19 '17 at 06:39
  • 4386427 thanks!!! I love this one!!! – galagala Aug 19 '17 at 06:46
  • 2
    `int new = 42;`, that's why :-) – paxdiablo Aug 19 '17 at 07:24
  • `printf` is also part of the standard `C++` libraries to make it easy to compile `C` programs using `C++`. There is no problem in keeping it. – Galik Aug 19 '17 at 07:46
  • From the rules: "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Donald Duck Aug 19 '17 at 20:58
  • sorry for that, I will pay attention to the rule next time. – galagala Aug 20 '17 at 06:40
  • See [Incompatibilities Between ISO C and ISO C++](http://david.tribble.com/text/cdiffs.htm) – Sparkler Sep 26 '18 at 20:43

5 Answers5

17

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
6

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).

There is no need to replace printf() with cout. But at the same time it is not quite so simple as "Compile C code with a C++ compiler."

You'll need to run all your tests, QA, and verification steps, just as if you were porting to a new operating system. This is because C++ is not actually 100% backward compatible with C code. There are a few ways that C code may have been written which will break if compiled with a C++ compiler.

If you're lucky, a C++ compiler with all warnings enabled will highlight any problematic portions of your C code. If you're less lucky, a small fraction of your C code may need to be updated to compile with a C++ compiler and run properly.

Try it. Test it. But don't bother trying to remove printf(), which is a perfectly nice function and still supported in C++.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
5

C++ is not a strict superset of C. That is, legal C code is not necessarily legal C++ code. Many of the typical differences are not syntactically valid in C++ and will fail to compile. For example:

  • Implicit void* to T* casts.
  • Using identifiers that happen to be C++ keywords.
  • Most features added to C in C99 or later.

A C++ compiler will generate errors about those, so those aren't too hard to find and fix if you have some patience.

Some differences could be valid in both languages but behave differently, however. Such cases are harder to detect. Some examples are shown at:

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
3

GCC stands for GNU Compiler Collection, is an integrated distribution of compilers for several major programming languages. These languages are C, C++, Objective-C, Objective-C++, Java, Fortran, and Ada, etc. This means internally its:

  • gcc: cc1 for C
  • g++: cc1plus for C++

You can try this with -x option and detail are here. Say, you want to compile your *.c files or *.cpp files use respective commands: gcc -xc -lstdc -shared-libgcc (or -static-libgcc) or gcc -xc++ -lstdc++ -shared-libgcc (-static-libgcc) respectively.

The differences are:

gcc will compile *.c/*.cpp files as C and C++ respectively, whereas g++ will compile *.c/*.cpp files but they will all be treated as C++ files. Linking will also happen similarly i.e. g++ to link the object files it automatically links in the std C++ libraries (gcc does not do this).
 g++ also has additional macros.

So you can compile C code with g++ and in fact mix both C and C++ code. Finally, the executable size may also changes based on the compiler.

Milind Deore
  • 2,887
  • 5
  • 25
  • 40
-4

c++ language is backward compatible to all the c code , as it is the successor of c language . That is the main reason why your c code still compiles with g++. But for good programming practice write your code in c++ if u are compiling on g++ because PROBLEMS DO EXISTS.

Vishal
  • 18
  • 3
  • 5
    This is condractitory. *"PROBLEMS DO EXISTS"* vs *"backward compatible to all the c code"* (the former is not true anyway, C++ lacks VLAs and designated initializers). – HolyBlackCat Aug 19 '17 at 07:17