"What I can not create, I do not understand."
- Richard Feynman
Having spent the most part of my programming career using C++, it is even today still a language that continues to impress me on what it is capable of, in term of semantic and syntatic richness. I will chronicle here some of my own experiments with the language, which both serve as a means of documenting what I know and for enhancing my understanding thru being able to explain various C++ concepts.
C++ with Inline Assembly
This should actually belong to my Demo Coding section since that's where inline assembly is put to great use for lowlevel graphics programming. But since it's abit generic it got moved here with intention to showcase how it might be used for compare-and-swap operations (i.e. via CMPXCHG instruction) that is the basis of much lock-free concurrency work being done lately. The following C++/Inline assembly code reverse a byte value using inline assembly assuming 32-bit architecture. It is compilable and runnable in Visual Studio 2005
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char b = 0x96; // this is 10010110
unsigned char outbyte = 0;
printf("hex of input byte: %X\n", b);
__asm {
xor eax, eax
xor ebx, ebx
mov al, [b]
mov ecx, 0x8
loop1:
shr al, 1
jnc nocarry
shl ebx, 1
or ebx, 1
jmp next
nocarry:
shl ebx, 1
next:
dec cx
jnz loop1
mov [outbyte], bl
};
printf("hex of output byte : %X\n", outbyte); // this is 01101001
return 0;
}
Scope guard for deleting STL containers of object pointers
This is an attempt to create a scope guard object for auto deleting stl containers containing pointers to objects, while disabling their use for stl containers containing actual objects.
template <class Elem> struct ElementTraits;
//specialize it for pointer to objects
template<class Elem>
struct ElementTraits<Elem*>
{
typedef typename Elem* value_type;
};template <class Container>
class scopedPtrContainer
{
public:
// this line should scream error if Container does not contain pointers
typedef typename ElementTraits<typename Container::value_type>::value_type value_type;
scopedPtrContainer(Container& c) : container(c) {}
~scopedPtrContainer()
{
for(Container::iterator it = container.begin();
it != container.end(); ++it)
{
delete *it;
}
}
private:
Container &container;
};class X
{
public:
X(){cout << "X ctor" << endl;}
X(const X& a){cout << "X cpctor" << endl;}
~X(){cout << "X dtor" << endl;}
};int _tmain(int argc, _TCHAR* argv[])
{
X* x2 = new X;
X* x3 = new X;
X* x4 = new X;
list<X*> xlist;
xlist.push_back(x2);
xlist.push_back(x3);
xlist.push_back(x4);
scopedPtrContainer<list<X*> > listguard(xlist);
return 0;
}
The output from the above program should be as follows,
X ctor
X ctor
X ctor
X ctor
X dtor
X dtor
X dtor
X dtor
Compile-time numerical computations using templates
The following code features very simple fibonacci, summation, factorial and gcd computation. Seems fun on first encounter of this template concept but it gets monotonous after a while.
#include <iostream>
using namespace std;template<int a> struct Factorial { enum {value = a * Factorial<a-1>::value}; };
template<> struct Factorial<0> { enum {value = 1}; };template<int a> struct Sum { enum {value = a + Sum<a-1>::value}; };
template<> struct Sum<0> { enum {value = 0}; };template<int a> struct Fib { enum {value = a == 0 ? Fib<0>::value : a == 1 ? Fib<1>::value : Fib<a-1>::value + Fib<a-2>::value}; };
template<> struct Fib<0> { enum {value = 1}; };
template<> struct Fib<1> { enum {value = 1}; };template <int a, int b> struct gcd { enum {value = a == 0 ? b : gcd<b % a, a>::value}; };
template <int b> struct gcd<0, b> { enum {value = b}; };int main(int argc, char* argv[])
{
cout << "Factorial 5: " << Factorial<5>::value << endl;
cout << "Sum 5: " << Sum<5>::value << endl;
cout << "4th term of fibonacci sequence: " << Fib<4>::value << endl;
cout << "gcd of 84, 360 : " << gcd<84, 360>::value << endl;
}
Buffer overruns
What does the following code do?
void foo()
{
int i = 0;
int array[4];
for (i = 0; i <= 6; i++)
array[i] = 0;
}int _tmain(int argc, _TCHAR* argv[])
{
foo();
return 0;
}
It runs forever! This is verified on Visual C++ 2008 Express Edition.
In g++ (GCC) 4.1.2 on linux x86_64, the following works,
int main(int argc, char* argv[])
{
int i = 0;
int array[6];
for (i = 0; i <= 8; i++)
array[i] = 0;
return 0;
}
... due to the slight difference between how the two compilers layout their stack frames.