blender 10935 1280

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 thought, I decided to write about it. My reason is twofold:

  1. These 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 are evident because I write about the C++ core guidelines.

CPL.1: Prefer C++ to C

 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 must answer is: Can you compile the entire code with a C++ compiler?

The entire source code is available

Fine, you are almost done. Almost, because C is not a subset of C++. Here is a small and inadequate C program that 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)
    
}

 

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (open)
  • "Generic Programming (Templates) with C++": October 2024
  • "Embedded Programming with Modern C++": October 2024
  • "Clean Code: Best Practices for Modern C++": March 2025
  • Do you want to stay informed: Subscribe.

     

    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 no 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 subtle differences between a C and a C++ compiler.  I reduced the program to line (2): printf(“\nsizeof(\’a\’): %d\n\n”, sizeof(‘a’));. Here is 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 is not available

    These are the critical points.

    1. Use your C++ compiler to compile your main function. In contrast to a C compiler, a C++ compiler generates additional startup code 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 with the same calling conventions. A calling convention specifies a compiler’s method 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 you can define a function with the same name but different parameters. The compiler picks the correct 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 how the C++ compiler can distinguish the various functions. The C++ compiler encodes the type of the parameters additionally into the function name. This process is called name mangling and is specific for each C++ compiler. The process which is not standardized is often also called name decoration.

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

    Here are the names that the GCC 8.3 and 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 pleased to announce that the next post begins a series to CppInsight. CppInsight is an incredible tool that I use heavily in my posts and 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: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, Philipp Lenk, Charles-Jianye Chen, Keith Jeffery,and Matt Godbolt.

    Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.

    My special thanks to Embarcadero
    My special thanks to PVS-Studio
    My special thanks to Tipi.build 
    My special thanks to Take Up Code
    My special thanks to SHAVEDYAKS

    Modernes C++ GmbH

    Modernes C++ Mentoring (English)

    Do you want to stay informed about my mentoring programs? Subscribe Here

    Rainer Grimm
    Yalovastraße 20
    72108 Rottenburg

    Mobil: +49 176 5506 5086
    Mail: schulung@ModernesCpp.de
    Mentoring: www.ModernesCpp.org

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *