C / C++

Links

Literature List

AuthorTitle
Bjarne StroustrupThe C++ Programming Language 3. Edition
Ulrich BreymannC++ Eine Einführung
Namir Clement ShammasC++ für Dummies

How programs are being startet

A short overview about ELF and how programs are started in Linux.

Compiler Variables

Change C and C++ compiler:

export CC=gcc-3.2 CXX=g++-3.2

Debug C / C++ Crashes:

$ ulimit -c unlimited
$ gcc -g PRG
$ g++ -g PRG
$ ./PRG
- CRASH -
$ gdb PRG core
run
bt
up
down
print $VAR
break foo.cpp:301
delete 1

DDD - Data Display Debugger

Runtime profiling

GNU gprof

g++ -g -pg foo.cpp -o foo.run
./run
gprof foo.run gmon.out | less
gprof foo.run gmon.out -f Foo::myfunction | less

doxygen

doxygen doxygen (x)emacs

C-c d f
C-c d ;

File Structure

.h

#ifndef _myh1_h_
#define _myh1_h_

#include <iostream>

namespace my_program {
  extern int global1;
}

#endif /* _myh1_h_ */

.cpp

#include <GL/glut.h>


#include "cg3_ex1.h"


using namespace std;


namespace my_program
{
  int   global1 = 5;
  float global2 = 6.0;


  /**
   * comment here
   */

  void foo()
  {
  }


}


int main(int argc, char **argv)
{
  using namespace my_program;
  return 0;
}

Macros

In C++ try to avoid them.

#define FOO blabla
#define BAR(a,b) 1: a 2: b

(no ; at the end of the line necessary, FOO and BAR are just replaced everywhere).

Don't compile certain areas:

#define VERSION1
...
#ifdef VERSION1
...
#elseif
...
#endif

Don't forget parenthesis

#define SQUARE1(a) a*a
#define SQUARE2(a) (a)*(a)
SQUARE1(1+2) // 1+2*1+2
SQUARE2(1+2) // (1+2)*(1+2)

Text output

With printf

#include <stdio.h>
...
printf ("%s", "Hello World");
printf ("Number a: %d Number b: %ld", 42, 650000L);

Or with cout

#include <iostream>
...
using namespace std;
cout << "Number"    << 42  << endl;

Header

cout#include <iostream>
std::cout << std::setw(8) << foo << std::endl;#include <iomanip>
fabs(int)#include <cstdlib>
fabs(float)#include <cmath>

Variables

Normal

int  x;  x=5;  cout << x; // 5

Reference

int& r=x;      cout << r; // 5

Pointer

int* y;  y=&x; cout << y; // 5 if x is still valid, trouble otherwise
int* y;  y=new int; delete y;
int* z;  z=y;  cout << z  // 5
x=*z; cout << x // 5

Memory

int * ptr2=(int*)malloc(155*sizeof(int));
for (int i=0; i<155; i++) {
 std::cout << ptr2[i];
}

Size of the Variables

#include <limits>
#include <iostream>

int main()
{
  using namespace std;
  numeric_limits<int> INT;
  ...
  cout << "INT  Min: "    << INT.min()     << " Max: " << INT.max()     << " EP: " <<  INT.epsilon()    << endl;
  ...
}
 
intuintshortushortlongulongfloatdoubleldouble
min i486-2147483648+0-32768+0-2147483648+01.17549e-382.22507e-3083.3621e-4932
min amd64-2147483648+0-32768+0-9223372036854775808+01.17549e-382.22507e-3083.3621e-4932
max i486+2147483647+4294967295+32767+65535+2147483647+42949672953.40282e+381.79769e+3081.18973e+4932
max amd64+2147483647+4294967295+32767+65535+9223372036854775807+184467440737095516153.40282e+381.79769e+3081.18973e+4932
epsilon i48601.19209e-072.22045e-161.0842e-19
epsilon amd6401.19209e-072.22045e-161.0842e-19

Check in C if there was an overflow

const

Value of x can't be changed

const int               x=4;

Pointer points to a value which can't be changed

      int const *       z;
const int       *       z;

Const pointer, value can be changed

      int       * const z;

Pointer and value are const

      int const * const z;
const int       * const z;

Methods which don't modify class variables should be declared const

class Foo {
 public:
  int getX() const {
   return this->x;
  }
}

mutable / const_cast

Sometime you might want to modify an unimportant class variable in a const method, e.g. you might want to count how often a get method was accessed:

class Foo {
 unsigned int statistic_access_counter;
 public:
  int getX() const {
   this->statistic_access_counter'''++'''; // Error!
   return this->x;
  }
}

This won't be allowed by your compiler You can either use const_cast to get full write access:

class Foo {
 unsigned int statistic_access_counter;
 public:
  int getX() const {
   Foo * tmp='''const_cast'''<Foo *>(this);
   tmp->statistic_access_counter++;
   return this->x;
  }
}

or (which is the better solution) mark the unimportant variables which might to modified in const methods:

class Foo {
 '''mutable''' unsigned int statistic_access_counter;
 public:
  int getX() const {
   this->statistic_access_counter++;
   return this->x;
  }
}

Fields / Arrays

int * ptr2=(int*)malloc(155*sizeof(int));
for (int i=0; i<155; i++) {
 std::cout << ptr2[i];
}
int  a[3]; // a[0], a[1], a[2]
int  b[]= {10,11,42};
char c[]= {'a','z','m'};
int  d[2]={10,11,42}; // Error!
int  d[7]={10,11}; // a[2]==a[3]==...==a[6]==0
b={10,11,42}; // Error
 

c String Copy

Tricky example how to copy a 0 terminated c string.

mystringcopy(char * a, const char * b) {

 // A
 while(*b!=0) {
  *a=*b;
  a++;
  b++;
 }
 *a=0;

 // B
 while( (*a++=*b++) != 0 );

 // C
 while(  *a++=*b++       );

}

Variant B and C use the fact that a=b returns b.

Strings

char c[3];
c[0]='a';
c[1]='b';
c[2]=0;
char * c1=new char[3];
char * c2="ab";

Int to String

int i=1242;
int len=(int)floor(log(i)/log(10));
char c[16+l+1];
snprintf(c,sizeof(c),"This is my int: %d",i);
c[sizeof(c)-1]=0;

String to int

char c[5]="1242";
int i=atoi(c);
char *p, *s;
s = "20y";
int i2 = strtol(s,&p,0); // i2:20 p:y

string

string str2("abc");

C++ strings

Enumeration

enum           { FOO,   BAR   };
enum myenumtyp { FOO,   BAR   };
typedef enum   { FOO,   BAR   } myenumtyp;
enum myenumtyp { FOO=0, BAR=1 };

Enumerations are often better than normal constants because the compiler can check if you didn't miss one in e.g., a switch statemant.

Functions

Normal function which returns a value and copies the value of the parameter before using it:

int foo(int x) {
 return x++;
}

This does the same as the previous example. However the parameter is a (read only) reference to the original variable. This is faster for large objects:

int foo(const int& x) {
 return x++;
}

Here the parameter can be changed and all changes will persist when the function terminates:

void foo(int& x) {
 x++;
}

Return by reference. Important: Store the result into a reference variable, otherwise you get a copy.

int & foo() {
 return x;
}

int   a=foo();  // :-(
int & b=foo();  // :-)
 

Pointers to Functions

First two normal functions:

int DoIt1  (float a, int b, int c)
 {
  return a+b+c;
 }

int DoIt2  (float a, int b, int c)
 {
  return a*b*c;
 }

class MyClass {
 public:
  int DoIt3(float a, int b, int c)
  {
   return a+b*c;
  };
};

Define pointers for them:

int (         *foo)(float, int, int);
int (MyClass::*bar)(float, int, int)=&MyClass::DoIt3;
 

Assign the the pointers to the functions:

foo = DoIt1;
int result1 =   foo(1.0, 2, 3);
int result2 =  (*foo)(1.0, 2, 3);

foo = DoIt2;
int result3 = foo(1.0, 2, 3);

MyClass * f;
int result4 =  f->DoIt3(1.0, 2, 3);
int result5 = (f->*bar)(1.0, 2, 3);
 

A pointer as a parameter:

void myfunc(int (*foo)(float, int, int))
 {
  int result = foo(1.0, 2, 3);
 }

myfunc(&DoIt1);
myfunc(&DoIt2);

Parameters

void foo(bool a, bool b=false);

The second parameter is optional, default is false

void foo(bool a ...);

As many bool parameters as you need (at least one), see <cstdarg> how to get the parameters.

Classes and Objects

Define a class

class MyClass : public MyParentClass
 {
  public:
   MyClass();
   MyClass(int x);
   int my_method() const;
   static int getTime();

  protected:
   int my_var;

  private:
 };

MyClass::MyClass() {
..
}

int MyClass::MyClass(int x) : MyParentClass(59)
{
...
}

int MyClass::my_method() const {
...
}
int MyClass::getTime() {
...
//in java super()
this is super() for c++
MyParentClass::getTime();
...
}

This is the easiest way to create an instance of a class

MyClass   x(5);

Return a pointer to the new instance. You have to call delete to free it again if you do not need it anymore.

MyClass * x=new MyClass(5);
...
delete x;

If you do it this way you first get an instance of the class created with the default constructor and then you overwrite it immediately.

MyClass   x;
x=MyClass(42);

You should avoid this. This is tricky when you have a class with an attribute of the type of a class within it. For example this class Planet has an attribute of the type Vector3D

class Planet
{
 public:
  Planet(const double pMass, const double x, const double y, const double z);

 private:
  double mass;
  Vector3D position;
};

If you define your constructor like this

Planet::Planet(const double pMass, const double x, const double y, const double z)
{
 position=Vector3D(x,y,z);
}

just before the constructor is called an instance of the Vector3D class would be created with the default constructor. Then your constructor would override it again immediately. This is how you can avoid this and initialise the position attribute with your values

Planet::Planet(const double pMass, const double pRadius, const double x, const double y, const double z) : position(x,y,z)
{
 ...

Normally you define class in C++ via .h files (interfaces) and the implementation separately. Hier an example for this with a Vector class Vector3D.h

#ifndef _Vector3D_h_
#define _Vector3D_h_

#include <math.h>
#include <iostream>

class Vector3D
{
 public:
  // constructor
  Vector3D(const double pX, const double pY, const double pZ);

  // get the X value
  double   getX() const;

  // return a new Vector3D which is the sum of us and the other
  Vector3D add(const Vector3D &other) const;

  // the length of ourself
  double  length() const;

 private:
  double x,y,z;
};


// overwrite the << operator
std::ostream& operator<<(std::ostream &strm, const Vector3D &a);

#endif
 

Vector3D.cpp

Vector3D::Vector3D(const double pX, const double pY, const double pZ)
{
  x=pX;
  y=pY;
  z=pZ;
}

double Vector3D::getX() const
{
  return x;
}

double   Vector3D::length() const
{
  return sqrt(x*x+y*y+z*z);
}

std::ostream& operator<<(std::ostream &strm, const Vector3D &a)
{
  return strm << "X Value is " << a.getX();
}
 

Static methods and static variables

Note that you need exactly one additional definition of the static variables outside the class. If you implement a static method do not repeat the keyword static.

class MyOtherClass {

public:

  MyOtherClass() {
    z=0;
  }

  static int foo() {
    return ( MyOtherClass::x + MyOtherClass::y );
  }

  int bar() {
    return ( MyOtherClass::x + MyOtherClass::y + this->z );
  }

protected:
  static int y;
  static int x;
  int z;
};

// !!!
int MyOtherClass::x=0;
int MyOtherClass::y=0;
// !!!

int main() {
 ...
}

Separated into a .h file

#ifndef _MyOtherClass_h_
#define _MyOtherClass_h_

class MyOtherClass
{
public:
  MyOtherClass();

  static int foo();

  int bar();

protected:
  static int y;
  static int x;
  int z;
};

#endif
 

and a .cpp file:

#include "MyOtherClass.h"

// do not repeat "static" here
int MyOtherClass::x=0;
int MyOtherClass::y=0;

MyOtherClass::MyOtherClass() {
 z=0;
}

// do not repeat "static" here
int MyOtherClass::foo() {
 return ( MyOtherClass::x + MyOtherClass::y );
}

int MyOtherClass::bar() {
 return ( MyOtherClass::x + MyOtherClass::y + this->z );
}

 

Virtuell Methods

If you modify non-virtual methods in derivated classes you might be surprised that the method from the father class might be called. Evil if the the destructor method is one of these methods.

#include <iostream>
using namespace std;

class A {
public:
  int foo() {
    return 1;
  }

  virtual int bar() {
    return 1;
  }

  //~A() {         <------ Don't!
  virtual ~A() {
    //...
  }
};

class B : public A {
public:
  int foo() {
    return 2;
  }

  virtual int bar() {
    return 2;
  }

    //~B() {
  virtual ~B() {
    //..
  }
};

int main() {
 A a; B b; A * x; x=&b;
 cout << a.foo()  << a.bar()  << endl; // 11
 cout << b.foo()  << b.bar()  << endl; // 22
 cout << x->foo() << x->bar() << endl; // 12
 return 0;
}

Access Control

public:Everyone
protected:Only objects of this class + descendants
private:Only class

Try to make class variables private, methoden protected, avoid public.

Namespace

Group different parts of the program in its own namespace.

namespace Foo {
 double x;
 double getX();
}

namespace Foo_1 {...};
namespace Foo_2 {...};

namespace MyFoo=Foo_2;
 

So you can even give a namespace a different name. Easy to switch between different namespaces.

How to access elements of different namespaces

int y=Foo::x;

using Foo::getX;
using Foo;

You can also use using to make the protected method of you parent class a public method of yourself

class A {
 protected:
  double getX();
};

class B : public A {
 public:
  using A::getX;
};

Copy Constructor

Foo a;
Foo b=a;

ruft den Copy Konstruktor auf:

Foo::Foo(const Foo& a);

If your object has pointers to memory which has to be freed in the destructor this may cause problems:

Foo a;
Foo b=a;
Foo c;

The destructor is only called for a and c, for b the copy constructor is called instead. At the end the destructor for all of the is called and you may free memory twice.

If there is a matching constructor you can initialise an object via an assignment:

class complex {
public:
 complex(double r, double i) {this->re=r; this->im=i;}
 complex(double r)           {this->re=r; this->im=0;}
private:
 double re,im;
}

complex a=complex(2.3);
complex b=2.3;

Inheritance

Multiple Inheritance

class A                      {};
class B : public A           {};
class C : public A           {};
class D : public B, public C {};

A   A
|   |
B   C
  /
  D

Now there are two different A objects. Better declare a virtual inheritance to A:

class A                      {};
class B : public virtual A   {};
class C : public virtual A   {};
class D : public B, public C {};

  A
/  
B   C
  /
  D

Cast

FOO a;
BAR b=(BAR)a;

FOO * c;
BAR * d=(BAR *)c;

dynamic_cast / static_cast

Assume we have the following hierarchy

class A                      {};
class B                      {};
class C : public           A {};
class D : public           B {};
class E : public C, public D {};

 A   B
 |   |
 C   D
   /
   E

And want to cast an object of the type A* to one of the type B*. You can do that manually:

A * a;
C * c=(C*) a;
E * e=(E*)c;
D * d=e;
B * b=d;

Or with a dynamic_cast

B * b=dynamic_cast<B*>a;

This will fail of A has no virtual method with this error:

error: cannot dynamic_cast `a' (of type `class A*') to type `class B* ' (source type is not polymorphic)

static_cast is a bit faster, but has no checks if you're doing something reasonable. Avoid it.

typeid

Foo a;
Bar b;
if (typeid(a)==typeid(FOO)) ...
if (typeid(a)==typeid(BAR)) ...
if (typeid(b)==typeid(FOO)) ...
if (typeid(b)==typeid(BAR)) ...

Exceptions

try {
 ...
 throw(5);
 ...
 throw(5.0);
}
// default catch, catch all
catch(int a)
 {
 }
catch(float b)
 {
 }
catch(...)
 {
 }

If possible list all exceptions you will throw:

void foo() throw();
void foo() throw(X,Y);

If another is thrown unexpected will be called.

auto_ptr

Problem:

foo() {
 ...
 fopen(FILE);
 ...
 if (...) throw error1;
 ...
 fclose(FILE);
 ...
}

If an exception is thrown the will needs to be closed. Complicate to not miss any case. Tricky solution: Write a class which will open the file in its constructor and closes the file in the destructor:

class X {
 public:
   X() {  fopen(FILE); };
  ~X() { fclose(FILE); };
}

Now you can rewrite the example like this:

foo() {
 ...
 X x;
 ...
 if(...) throw error1;
 ...
}

Now the file will be closed whenever the object leave the scope (which will also happen when the exception is thrown). The is already a generic object for this available: auto_ptr from <memory>.

Exception is not only for Errors

Stack<int> data;

try
{
 for(;;) { data.pop(); }
}
catch(data::Empty)
{
 ...
}

Instead to check in the for header when to stop just catch the exception. (Too) Tricky, better avoid it.

Assertions

//#define NDEBUG
#include <cassert>
assert(a>0 && b<0);

Templates

Classtemplates

template <class Pairtype>
 class Pair
  {

   template class Pair<int>;
   template class Pair<double>;

   public:
    Pair();
    Pair(Pairtype left, Pairtype right);
    Pairtype get_left();
    void set_left(Pairtype left);

   protected:
    Pairtype left;
    Pairtype right;
  };
}
template <class Pairtype>
Pair<Pairtype>::Pair(Pairtype left, Pairtype right)
 {
  this->left=left;
  this->right=right;
 }

template <class Pairtype>
Pairtype Pair<Pairtype>::get_left()
 {
  return left;
 }

template <class Pairtype>
void Pair<Pairtype>::set_left(Pairtype left)
 {
  this->left=left;
 }
Pairtype<int> foo;

Singleton

class tg {
public:
  static tg& get_instance(void) {
        return tg::my_instance;
  }
private:
  static tg my_instance;
  tg() {

  }

  tg(const tg&);

  tg& operator=(tg&);
};

 tg tg::my_instance;

int main(int argc, char **argv)
{
  tg& a = tg::get_instance();
}

Operator

class MyClass {
 public:
 ...
 MyClass & operator+=(const MyClass & other);
}

friend bool operator< (const MyClass& a, const MyClass& b) {
   return a.foo<b.foo;
}

std::ostream& operator<< (std::ostream& os, const MyClass& a) {
  os << "Foo: " << a.foo << " Bar: " << a.bar << std::endl;
  return os;
}

Increment / Decrement Operator

// ++i
MyInt MyInt::operator++() {
 value+=1;
 return value;
}

// i++
MyInt MyInt::operator++(int) {
 MyInt rescue=value;
 value+=1;
 return rescue;
}

Iterators

vector <ContainerType>                           a;
vector <ContainerType>::iterator            iter_a;
vector <ContainerType>::const_iterator constiter_b;
vector <ContainerType> c;
vector <ContainerType>::reverse_iterator inter_r;

iter_b=c.end();
iter_a=c.begin();
(*iter_a)=c.at(0);
while (iter_a!=c.end())
 {
  cout << *iter_a;
  iter_a++;
 }

if (c.end()!=c.begin()) {
 iter_a=c.end();
 do {
  iter_a--;
  cout << *iter_a << endl;
 } while (iter_a!=c.begin());
}

for (iter_r=c.rbegin(); iter_r!=c.rend(); iter_r++) {
 cout << *iter_r << endl;
}

for(iter_a=c.begin(),x=0;
    iter_a!=c.end() && x<100;
    iter_a++, x++
   ) {}

back_insert_iterator

If you like to insert something in a container you need a reasonable iterator. b.end() points behind the end of the container, b.begin() would overwrite elements. Solution: back_insert_iterator

#include <vector>
#include <list>
#include <iostream>

using namespace std;
int main() {

  vector<int> a;
  vector<int> b;

  a.push_back(1);
  a.push_back(2);
  a.push_back(3);
  copy(a.begin(), a.end(), back_insert_iterator<vector< int > >(b));

  // 1
  // 2
  // 3
  for(vector<int>::const_iterator i=b.begin(); i!=b.end(); i++)
    cout << *i << endl;
  cout << endl;

  list<int>                             myList;
  back_insert_iterator<  list< int > >  myListIteratorBack(myList);
  front_insert_iterator< list< int > >  myListIteratorFront(myList);

  myListIteratorBack=4;
  myListIteratorBack=5;
  myListIteratorFront=6;

  // 6
  // 4
  // 5
  for(list<int>::const_iterator i=myList.begin(); i!=myList.end(); i++)
    cout << *i << endl;
  cout << endl;

}

Functions to Walk Through a stl Container

Try not to iterate through the container yourself

vector<int> a;
for(vector<int>::iterator i=a.begin(); i!=a.end(); i++) foo(*i);

instead use stl functions for that:

sort(a.begin(), a.end());
for_each(a.begin(), a.end(), foo);

The last one won't work with methods (only function). If you have a class:

class X {
public:
 void draw();
}

and want to call a method of each element use a function for that:

vector<X *> data;

void foo(X * x) {
 x->draw();
}

for_each(data.begin(), data.end(), foo);

There is already a function called mem_fun for this:

for_each(data.begin(), data.end(), mem_fun(&X::draw));

List with useful functions:

Sort with a Functor

functor

class mycomp {
public:
 bool operator()(double x, double y) { return fabs(x) < fabs(y); }
};

vector<double> data;
sort(data.begin(), data.end(), mycomp());

Control Flow

continue

Skips the rest of the current loop run and starts the next one

for (int i=0; i<5; i++) {
 std::cout << "n";
 std::cout << i << " ";
 if (i==2) continue;
 std::cout << i;
}

Output

0 0
1 1
2
3 3
4 4

break

Skips the whole loop

for (int i=0; i<5; i++) {
 std::cout << "n";
 std::cout << i << " ";
 if (i==2) break;
 std::cout << i;
}

Output

0 0
1 1
2

Beside continue and break there is also goto! ;-)

goto foo;
...
foo:
 ...

Conditional Expressions

if  (a<=b)   max=a; else max=b;
max=(a<=b) ?     a   :       b;

Memory Leaks

If you create something with new you have to take care to delete it with delete afterwards. But watch out to not use foo afterwards!

Foo *foo = new Foo;
...
delete foo;
...
return foo; // no!

unique_ptr

Use variables of the type unique_ptr to hold your pointers. Once those variables get recycled by the Garbage Collector they will take care of your pointers.

So instead of doing this

Foo * my_function()
{
 Foo *foo = new Foo;
 if(problem)
 {
  delete foo;
  return NULL;
 }
 foo->doSomethingWithMe();
 return foo;

do this

Foo * my_function()
{
 unique_ptr<Foo> foo(new Foo); // this is new
 if(problem)
 {
  return NULL; // no more delete needed, once foo goes it takes the pointer with it
 }
 foo->doSomethingWithMe(); // works like it did before
 return return foo.release(); // from now one you will have to delete it again once you are done
}

If the receiver accepts and unique_ptr type you can use

move(foo)

to pass the responsibility and ownership safely away.

Find C / C++ Memoryleaks

valgrind

valgrind --leak-check=yes --show-reachable=yes ./MYPROGRAM

memprof

alleyoop

Use two different C++ Compiler Versions for one Project

Assume you have the following small project: new.cpp

#include "old.h"

class newClass
{
public:
  int newClassMethod(int x) {
    return proxy(x);
  }

};

int main(int argc, char **argv) {
  newClass newObject;
  return newObject.newClassMethod(5);
}

old.h

int proxy(int x);

old.cpp

#include "old.h"

class oldClass
{
public:
  int myold(int x) {
    return 25;
  }
};

int proxy(int x) {
  oldClass oldObject;
  return oldObject.myold(x);
}

In new.cpp there is an object of the newClass class which uses code from the file old.cpp. This project should compile without problems:

g++-2.95 -c old.cpp   -o old.o
g++-2.95 -c new.cpp   -o new.o
g++-2.95 old.o new.o  -o myproject

Things get interesting if you have to compile old.cpp with g++-2.95 (e.g. because you don't have access to the sources of old.o to recompile it) and want to compile the rest with a newer compiler

g++-2.95 -c old.cpp   -o old.o
g++-3.3  -c new.cpp   -o new.o
g++-3.3  old.o new.o  -o myproject

This will fail

new.o(.gnu.linkonce.t._ZN8newClass14newClassMethodEi+0xd): In function `newClass::newClassMethod(int)':
: undefined reference to `proxy(int)'

collect2: ld returned 1 exit status

because the ABI between gcc-3.2 and the ABI of previous versions differ. However there is a way to circumvent this. Just offer in one of the files, which also has been compiled with an old version of the compiler, a C function which can be uses as a interface between both worlds. This works because the ABI only changed for C++ code and not for C code. Everything we have to do in our example is to declare this function as a C function: old.h

extern "C"
{
 int proxy(int x);
}

Now it can be used as an interface between both worlds.

However there are still problems if the new and the old files like to use for example the stl libs. This is how you can fix it: Example project: , , , , , , .

First compile all the files with their matching compiler

g++-2.95 -c old.cpp      -o old.o
g++-2.95 -c oldClass.cpp -o oldClass.o
g++-3.3  -c new.cpp      -o new.o
g++-3.3  -c newClass.cpp -o newClass.o

Now combine all old .o files to one static file .o. This will show you how to do it:

g++-2.95 -v -static -r -o allOldStuff.o   old.o oldClass.o

Be careful not to include the same file twice in the next step so remove some of the .o files from the command line until the next steps works without errors about duplicates. It may look like this:

/usr/lib/gcc-lib/i386-linux/2.95.4/collect2 -m elf_i386 -static -o allOldStuff.o -r -L/usr/lib/gcc-lib/i386-linux/2.95.4 old.o oldClass.o -lstdc++ -lm -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-linux/2.95.4/crtend.o /usr/lib/crtn.o

Everything that is left is to combine all new .o files against the .o you created from all the old files:

g++ -o MyProgram  new.o newClass.o allOldStuff.o

Done :-)

Sadly it looks there are run-time problems with this solution.

True Story of Hello World

The True Story of Hello World

# gcc -Os -c hello.c
# objdump -hrt hello.o
# gcc -Os -S hello.c -o -
# ld -static -o hello -L`gcc -print-file-name=` /usr/lib/crt1.o /usr/lib/crti.o hello.o /usr/lib/crtn.o -lc -lgcc

void bar()
{
  int x=42;
  int y=51;
  int array[2]={18,19};

  walker=&array[0];
  walker--;
  do
  {
    walker++;
    printf("Walking dead address %d value %d \n", walker, *walker);
  } while(*walker!=88);
}

Walking dead address 2272280 value 18
Walking dead address 2272284 value 19
Walking dead address 2272288 value 51
Walking dead address 2272292 value 42
Walking dead address 2272296 value 2272328
Walking dead address 2272300 value 4198815
Walking dead address 2272304 value 4202629
Walking dead address 2272308 value 99

Thanks

Thanks to Richard Eckart for his support