We have covered the C calling convention, frame pointers and the assembly code in the previous article. This article will focus on the code generation for:
We have covered the C calling convention, frame pointers and the assembly code in the previous article. This article will focus on the code generation for:
With the advent of mobile devices, optimizing code has become even more important. Faster applications not only improve the user experience, they also improve battery life.
Optimizing C++ and C Code discusses several techniques that will help improve the performance.
C++ header file management can be very frustrating:
Here are a few rules to remedy this:
An example of illustrates the header file inclusion rules:
#ifndef _a_h_included_ #define _a_h_included_ #include "abase.h" #include "b.h" // Forward Declarations class C; class D; class A : public ABase { B m_b; C *m_c; D *m_d; public: void SetC(C *c); C *GetC() const; void ModifyD(D *d); }; #endif
#include "a.h" #include "d.h" void A::SetC(C* c) { m_c = c; } C* A::GetC() const { return m_c; } void A::ModifyD(D* d) { d->SetX(0); d->SetY(0); m_d = d; }
For details, refer to: C++ Header File Include Rules
We have already looked at mapping from C++ classes and methods to C structures and functions in a previous blog post. Here we will map inheritance and virtual functions to C code.
This blog post is based on the article mapping from C++ inheritance and virtual functions to C code. The contents of the article are summarized below.
A C++ base class with virtual functions requires extra logic to support the machinery for handling virtual functions. The following C++ base class….
class Shape { protected: int m_x; int m_y; public: virtual void Draw() = 0; virtual void MoveTo(int newX, int newY); void Erase(); Shape(int x, int y); virtual ~Shape(); };
…maps to the following C code.
typedef void (*VirtualFunctionPointer)(...); struct VTable { int d; /* d and i are used in multiple inheritance */ int i; VirtualFunctionPointer pFunc; }; VTable VTableArrayForShape[] = { { 0, 0, (VirtualFunctionPointer) pure_virtual_called_error_handler }, { 0, 0, (VirtualFunctionPointer) Shape_MoveTo }, { 0, 0, (VirtualFunctionPointer) Shape_Destructor } }; struct Shape { int m_x; int m_y; VTable *pVTable; };
Points to note here are:
For details refer to the article: Mapping from C++ inheritance and virtual functions to C code
The inheriting Circle class….
class Circle : public Shape { private: int m_radius; // Radius of the circle public: // Override to draw a circle virtual void Draw(); // Constructor for Circle Circle(int x, int y, int radius); // Destructor for Circle virtual ~Circle(); };
…maps to a new VTable array and a new struct:
VTable VTableArrayForCircle[] = { { 0, 0, (VirtualFunctionPointer) Circle_Draw }, { 0, 0, (VirtualFunctionPointer) Shape_MoveTo }, { 0, 0, (VirtualFunctionPointer) Circle_Destructor } }; struct Circle { /* Fields inherited from Shape */ int m_x; int m_y; VTable *pVTable; /* Fields added by Circle */ int m_radius; };
For details refer to the article: Mapping from C++ inheritance and virtual functions to C code
A virtual function call like…
pShape->Draw();
…is replaced by a call through a virtual table function pointer.
(pShape->pVTable[0].pFunc)(pShape);
We have covered basics of inheritance handling here. For details about constructor and destructor definitions and vtable array pointer initialization refer to the article: Mapping from C++ inheritance and virtual functions to C code.
C++ internals can be better understood by mapping them to corresponding C code.
Refer to the article mapping from C++ classes and methods to C structs and functions.
The contents of the article are summarized below.
A C++ method maps to a C method with an additional this pointer. For example, the UpdateX
method C++ method…
void A::UpdateX(int newX) { if (g_y != 0 && m_x < newX) { m_x = newX; } }
…translates to the following C code:
void A_UpdateX(A *this_ptr, int newX) { if (g_y != 0 && this_ptr->m_x < newX) { this_ptr->m_x = newX; } }
Complete article: Mapping from C++ classes and methods to C structs and functions.
A C++ class is equivalent to a C structure with a class methods. The following class…
class A { private: int m_x; static int g_y; int m_z; // Should be invoked when the object ends void InformEnd(); public: A(int x); ~A(); void UpdateX(int newX); static void UpdateY(int newY); };
…is represented as the C structure with functions.
struct A { int m_x; int m_z; }; int g_y = 0; /* Represents static variable */ A *A_Constructor(A *this_ptr, int x); void A_Destructor(A *this_ptr, BOOLEAN dynamic); void A_UpdateX(A *this_ptr, int newX); void A_UpdateY(int newY); /* Represents a static method. */
Complete article: Mapping from C++ classes and methods to C structs and functions.
In C++, objects may be allocated on the heap or the stack. This has implications in the mapping from a C++ constructor to an initialization function in C.
A::A(int x) { m_x = x; m_z = 0; }
The mapped constructor takes an additional this pointer. A NULL is passed as the this pointer when the object has to be allocated on the heap. A valid stack address is passed when an object is on the stack.
If a NULL pointer is passed to the construction function, it allocates memory before performing the initialization.
A *A_Constructor(A *this_ptr, int x) { /*Check if memory has been allocated for struct A. */ if (this_ptr == NULL) { /*Allocate memory of size A. */ this_ptr = (A *) malloc(sizeof(A)); } /* Once the memory has been allocated for A, initialize members of A. */ if (this_ptr) { this_ptr->m_x = x; this_ptr->m_z = 0; } return this_ptr; }
Complete article: Mapping from C++ classes and methods to C structs and functions.
Destructors also deal with deletion of stack and heap objects.
A::~A() { InformEnd(); }
If the object was allocated on the heap, a boolean is passed to signal to the construction function that the memory was allocated dynamically and needs to be freed.
void A_Destructor(A *this_ptr, BOOLEAN dynamic) { InformEnd(this_ptr); /* If the memory was dynamically allocated for A, explicitly free it. */ if (dynamic) { free(this_ptr); } }
Complete article: Mapping from C++ classes and methods to C structs and functions.