C++ Core Guidelines: Mixing C with C++

Due to the same history of C and C++, both languages are closely related. Because neither of them is a subset of the other, you have to know a few rules to mix them.

blender 10935 1280

The chapter in the C++ core guidelines is called: C-style programming. Honestly, my first thought was to skip it, but after more thoughts I decided to write about it. My reason is twofold:

  1. This are the typical issues we have when dealing with legacy code.
  2. One reader wanted that I write more about the challenges of legacy code.

Here are the three rules for today:

The first rules is obvious because I write about the C++ core guidelines.

CPL.1: Prefer C++ to C

 Without further ado, the reason from the C++ core guidelines: "C++ provides better type checking and more notational support. It provides better support for high-level programming and often generates faster code."

CPL.2: If you must use C, use the common subset of C and C++, and compile the C code as C++

The first question you have to answer is: Can you compile the entire code with a C++ compiler?

Entire source code available

Fine, you are almost done. Almost, because C is not a subset of C++. Here is a small and bad C program which will break with a C++ compiler.

// cStyle.c

#include <stdio.h>

int main(){

    double sq2 = sqrt(2);                           // (1)
    
    printf("\nsizeof(\'a\'): %d\n\n", sizeof('a')); // (2)
    
    char c;
    void* pv = &c;
    int* pi = pv;                                   // (3)
    
    int class = 5;                                  // (4)
    
}

 

First, let me compile and execute it with the C90 standard.

The compilation succeeds with a few warnings.

cStyleC2

The program cStyle.c has a few issues. There is not declaration for the sqrt function (line 2), line (3) performs an implicit conversion from a void pointer to an int pointer, and line (4) uses the keyword class.

Let's see what the C++ compiler is saying.

cStyleCpp

I get what I deserve: three compiler errors. The program cStyle.c shows are more subtile difference between a C and a C++ compiler.  I reduced the program to the line (2): printf("\nsizeof(\'a\'): %d\n\n", sizeof('a'));. Here ist the output.

cStyleCppSizeof

Instead of 4 such as for the C compiler, sizeof('a') is 1 with the C++ compiler. 'c' is an int in C.

Now, to the more challenging job.

Entire source code not available

This are the important points.

  1. Use your C++ compiler to compile your main function. In contrast to a C compiler, a C++ compiler generates additional startup code which is executed before the main function. For example, this startup code calls constructors of global (static) objects.  
  2. Use your C++ compiler to link your program. The C++ compiler, when used for linking the program, will automatically link in the standard C++ libraries.
  3. Use a C and C++ compiler from the same vendor which should have the same calling conventions. A calling convention specifies the method that a compiler sets up to access a function. This includes in which order parameters are allocated, how parameters are passed, or whether the caller of the callee prepares the stack. Read the full details of x86's calling conventions on Wikipedia.

CPL.3: If you must use C for interfaces, use C++ in the calling code using such interfaces

In contrast to C, C++ supports function overloading. This means that you can define a function having the same name but different parameters. The compiler picks the right function when a function is invoked.

// functionOverloading.cpp

#include <iostream>  
  
void print(int) { 
    std::cout << "int" << std::endl; 
} 

void print(double) { 
    std::cout << "double" << std::endl; 
} 

void print(const char*) { 
    std::cout << "const char* " << std::endl; 
} 

void print(int, double, const char*) { 
    std::cout << "int, double, const char* " << std::endl; 
} 

  
int main() { 
 
    std::cout << std::endl;   

    print(10); 
    print(10.10); 
    print("ten"); 
    print(10, 10.10, "ten");

    std::cout << std::endl;

}

 

The output is as expected.

functionOverloading

The exciting question is now: How can the C++ compiler distinguish the various functions? The C++ compiler encodes additionally the  type of the parameters into the function name. This process is called name mangeling and is specific for each C++ compiler. The process which is not standardised is often also called name decoration.

With the help of the functionOverloading.cpp on compiler explorer, it is quite easy to show the mangled name. Just disable the button Demangle.

Here are the names that the GCC 8.3 and the MSVC 19.16 is producing.

Mangling

By using the extern "C" linkage specifier, you can prevent the C++ compiler from mangling the names.

By declaring the function with extern "C" in your code, you can call a C function from C++, or a C++ function from C.

You can use extern "C" for each function,

extern "C" void foo(int);

for each function in a scope,

extern "C" {
    void foo(int);
    double bar(double);
};

 

or for the entire header file by using include guards. The macro __cplusplus is defined when the C++ compiler is used.

#ifdef __cplusplus
extern "C" {
#endif
    void foo(int);
    double bar(double);
    .
    .
    .
#ifdef __cplusplus
}
#endif

What's next?

I'm totally happy to announce that with the next post begins a series to CppInsight. CppInsight is an awesome tool which I use heavily in my posts and in my classes to show the magic of the C++ compiler. But the tool lacks a good introduction. Who can be better equipped for writing this introduction as Andreas Fertig, the author of CppInsight?

 

Thanks a lot to my Patreon Supporters: Paul Baxter,  Meeting C++, Matt Braun, Avi Lachmish, Roman Postanciuc, Venkata Ramesh Gudpati, Tobias Zindl, Dilettant, Marko, Ramesh Jangama, G Prvulovic, and Reiner Eiteljörge.

Thanks in particular to:  TakeUpCode 450 60

 

Get your e-book at Leanpub:

The C++ Standard Library

 

Concurrency With Modern C++

 

Get Both as one Bundle

cover   ConcurrencyCoverFrame   bundle
With C++11, C++14, and C++17 we got a lot of new C++ libraries. In addition, the existing ones are greatly improved. The key idea of my book is to give you the necessary information to the current C++ libraries in about 200 pages.  

C++11 is the first C++ standard that deals with concurrency. The story goes on with C++17 and will continue with C++20.

I'll give you a detailed insight in the current and the upcoming concurrency in C++. This insight includes the theory and a lot of practice with more the 100 source files.

 

Get my books "The C++ Standard Library" (including C++17) and "Concurrency with Modern C++" in a bundle.

In sum, you get more than 600 pages full of modern C++ and more than 100 source files presenting concurrency in practice.

 

Get your interactive course

 

Modern C++ Concurrency in Practice

C++ Standard Library including C++14 & C++17

educative CLibrary

Based on my book "Concurrency with Modern C++" educative.io created an interactive course.

What's Inside?

  • 140 lessons
  • 110 code playgrounds => Runs in the browser
  • 78 code snippets
  • 55 illustrations

Based on my book "The C++ Standard Library" educative.io created an interactive course.

What's Inside?

  • 149 lessons
  • 111 code playgrounds => Runs in the browser
  • 164 code snippets
  • 25 illustrations
Tags: C

Add comment


My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 877

All 2910050

Currently are 174 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments