Table of Contents

Namenskonventionen

Basics

Cis a pass-by-value language. \\ It is only possible to pass something (Object or primitive type) by reference, by explicitely expecting a reference. <sxh cpp> //SomeType& is a reference Type void swap(SomeType& arg1, Sometype& arg2) { SomeType temp = arg1; arg1 = arg2; arg2 = temp; } ... SomeType var1 = "A"; SomeType var2 = "B"; swap(var1, var2); // swaps their values! // now var1 has value "B" and var2 has value "A" </sxh> == Ausdruck und Anweisung == {{ http://i42.tinypic.com/jr2ltt.png }} == Runden == Beachte, dass FALSE in c als 0 behandelt wird. Somit wird im folgenden Vergleich der linke Teil zu 0 oder 1 ausgewertet und dann mit c verglichen <code> a<b<c -> 0<c 1<c </code> == Typedefinition == An additional variable type is defined with the syntax: typedef oldType newTapyAlias. E.g. an alias "newVarTypeName" for int is defined as following: <code> typedef int newVarTypeName </code> == Konstante == Eine Konstante welche in allen Scopes gültig ist kann definiert und wieder zurueck "undefiniert" werden: <code> #define ConstantName constantValue const ConstantName2 constantValue2 #undef ConstantName #undef ConstantName2 </code> == Bitarithmetik == Eine Konstante welche in allen Scopes gültig ist kann definiert und wieder zurueck "undefiniert" werden: <code> a&b AND a

3 == pow ( pow(3,0.5) , 2 )  //bei den Berechnungen kann der linke Teil um eine winzige Zahl kleiner als 3 werden, somit wird er abgerundet und wird zu 2

=== Speicherverwaltung === C kann Speicherbereiche gezielt adressieren. Dazu wird der folgende Mechanismus benutzt: == Wichtige unäre operatoren == * ist der dereferenzeoperator. Er löst einen Pointer auf einen Objekt auf. & ist der address-of operator. Er liefert die Adresse, an welcher der Objekt in der übergebenen Variable gespeichert ist.

*Pointer = <Pointer-Ziel> //in Java ist der Punkt-Operator der äquivalent zum Stern operator. Objektname.var löst "Objektname" zu einem Objekt auf.
&Variable = <Adresse des Objektes in der Variablen>



Vorweg:
Referenzen sind statische Ersatznamen für eine Objekt.
Pointer sind Objekte, die auf Speicherbereiche zeigen und mithilfe des dereferenzoperators (*) die Objekte in diesem Speicherbereich liefern koennen.
Pointer können umgehangen werden

Ein tolle Erklärung zum Thema Pointer und Referenzen:
http://www.cplusplus.com/doc/tutorial/pointers/ == Referenz== Eine Referenz sollte man als einen Ersatznamen eines Objektes sehen. JEDES Auftreten einer Referenz wird vor dem Anfang JEDER Operation darauf zu deren Zielobjekt aufgelöst. Deswegen sind Referenz-Objekte selbst (nicht die Objekte für die sie als Ersatznamen dienen) - nach deren Erzeugung nicht mehr greifbar. In C sind Referenzen typisiert, genau wie variablen. (In C gibt es Referenzen nicht als Typ, nur Pointer). Referenztypen werden aus VariablenTypeNamen mit angehängeten & erzeugt. Eine Referenz als Ersatznamen fuer A erstellt man wie folgt:

int A
int& referenzName = A;

Eine Referenz muss sofort bei der Definition und für immer initialisiert werden. Die Referenz kann nicht auf ein anderes Ziel “umgehangen” werden. Pointer können “umgehangen” werden.

int& meineReferenz ; // compiler will complain: error: `meineReferenz' declared as reference but not initialized

Trotz des Vorkommens von '&' Zeichen und obwohl die Referenzen als Pointer implementiert sind - hat das Konzept der Referenz nichts mit dem Speicher zu tun. Deswegen wird der Referenz bei der Initialisierung - das Objekt selbst zugewiesen und nicht etwa dessen Adress im Speicher.

int var = 2;
int& meineReferenz = var;

Der Typ der Referenz in der Objekorientierten Welt wird durch das anfügen des & zeichen RECHTS an dem Variablentyp gebildet.

typeof ( meineReferenz )  // int&
Pointer

Einen Pointer sollte man wie ein Objekt betrachten, welches auf eine Adresse zeigt, genau wie Referenzen. Ein Pointer ist nur eine Möglichkeit die im Speicher abgelegte Variable anders zu benennen. Im gegensatz zu den Referenzen können Pointer:

Ein Pointer auf eine Variable sieht wie folgt aus:

*pointerName

Initialisierung des Pointers sieht so aus:

int * number;
char * character;
float * greatnumber;

Pointer werden zusammen mit dem “adress-of” Operator benutzt. Vor der Pointerdefinition muss der TypName der Variablen stehen, auf dessen Speicher der Pointer später zeigen soll. zB bei Integer siehts so aus:

double varA = 2;
double varB = 3;
double* pointerName;  //neuer Pointer auf int Variablen namens "pointerName" definiert
pointername = &varA; //der Pointer "ponterName" zeigt nun auf die Adresse der Variablen. Er kann, zusammen mit dem Dereferenzoperator den Inhalt von varA liefern
echo (*pointername); //liefert 2
echo (pointername);  //liefert die MEMORY-ADRESSE der Variablen varA. Die Adresse ist ein int Wert.

Der Typ des Pointers in der Objekorientierten Welt wird durch das anfügen des Sterns RECHTS an dem Variablentyp gebildet:

typeof ( *pointerName )  // double*
typeof (  pointerName )  // int

Es ist möglich einen Pointer mit einem unbestimmten Typ zu erstellen, indem man void* als typ nimmt. bei solchen Zeigern hat der Kompiler aber keine Ahnung, was fuer eine Information im Speicher liegt. Sie muss gecastet werden.

	int a = 22222222;
	void* test = &a; // compiler doesn't know, that test points to int
	int* b = reinterpret_cast<int*>(test); // reinterpret the pointer test as pointer to int
	std::cout << *b << endl; // gives 22222222

Entsorgung des Pointers

Weil mehrere Pointer auf eine Adresse zeigen können wird nach dem “Umhängen des Pointers” auf andere Adresse der Speicher nicht freigegeben. Es muss explizit gemacht werden durch

delete pointerName
Struct

Ein struct ist eine möglichkeit mehrere Variablen in einem Objekt zu kapseln.
Gekapselte Variablen dürfen nicht initiiert worden sein.

struct Computer{
int ram;
int mhz;
int terrabyte;
}

Typedef can be used, to define a struct as a new encapsulation object.

typedef struct{
int x;
int y;
} Point;

//after that you can use a Point construct.

Point a;
a.x = x;
a.y = y;
return a;

Union

Wie struct, nur teilen sich die, im union definierten variablen, den Speicherplatz.

Arrays

Die Arrays in Csind als Pointer implementiert. Der Name des Arrays zeigt auf eine Adresse im Speicher, wo das erste Array-Element gespeichert ist. Um das nächste Element aus dem Array zu holen - bewegt das System den Zeiger um \\sizeof (TYPE)\\ weiter im Speicher. Da Arrays als Pointer implementiert sind - kann ein Array auf zwei wegen definiert werden: - Indem der ganze Speicher dem Array sofort bei der Definition zugewiesen wird. <sxh cpp> int arrayName[] = {1,2,3,4,5} //das Array mit 5 Elementen int arrayName[5] = {1,2,3} //das Array mit 5 Elementen, wovon 3 initialisiert werden. Dem Array wird trotzdem sofort der ganze Speicher 5* sizeof(int) zugewiesen. </sxh> - Indem der nötige Speicher erst bei der späteren Initiierung vom freispeicher geholt und dem Array zugewiesen wird. <sxh cpp> int* arrayName; //der Array wird als Pointer initiiert. Nutze das Wissen ueber die Implementierung des Arrays als Pointer aus. arrayName = new int[5]; //erst jetzt wird der nötige Speicher vom Freispeicher abgeschnitten und dem Array zugewiesen. </sxh> == Gefährliche Syntax == <sxh cpp> //ATTENTION: //Pointer depth 1 int marr[] = {1,13,25,37,45,56}; // array is implemented as a Pointer TO THE FIRST ARRAY ELEMENT int* pmarr = marr; // don't use & for assignment, because same pointer depth. Assigning Pointer = Pointer makes them equal. So pmarr points to the first ArrayElement. int* point = (marr + 1); // ATTENTION: moves the array-pointer in memory, but by sizeof(TYPE) and not by 1 byte. The steps are equal to the type of the array-elements (here sizeof(int)) //Pointer depth 2 int** ppmarr = &pmarr; // use & because going one level deeper. So use the address of the pointer. //TYPES //array and pointer are different, which can be seen by checking their types std::cout << "type of marr is: " << typeid(marr).name() << std::endl; // int* so marr gives a pointer to the first array element std::cout << "type of &marr is: " << typeid(&marr).name() << std::endl; // int (*)[6] so &marr gives a pointer to the whole array std::cout << "type of pmarr is: " << typeid(pmarr).name() << std::endl; // int* so pmarr gives a pointer to the first array element std::cout << "type of &pmarr is: " << typeid(&pmarr).name() << std::endl; // int** so &pmarr gives a pointer to to pointer to the first array elelemt. Because & gets us one level deeper. </sxh> == Funktionen == Die Funktionen werden, wie in Java, definiert. 2 Unterschiede gibt es: - Parameter der Funktionen können mit default werten initiiert werden. Bei der Nutzung der Funktionen können diese Parameter dann ausgelasssen werden.<sxh cpp> void Func(int one, int two, int three){ return one+two+three; } void Func(one = 1, two=2, three=3); Func(10,20,30); //return 10+20+30=60 Func(10,20); //dont define the last param return 10+20+3=33 Func(10); //dont define the last 2 params return 10+2+3=15 </sxh> **ACHTUNG:** \\ wird ein Array als Funktions-Parameter erwartet, so wird auch ein Pointer an seiner Stelle angenommen, weil Arrays - als Pointer implementiert werden. <sxh cpp> void Func(int[] mArray){ ... } int[] arrOne = {1,2,3} Func(arrOne); //valid call, expected behaviour int* arrPointer; Func(arrPointer); //valid call, unexpected behaviour </sxh> Dabei muss man zwei sachen beachen: - der Pointer muss mit **delete** explizit vernichtet werden, um den SPeicher frei zu geben, - die Arrays werden "by reference" übergeben, wenn man mit dem Array-Funktionsparameter arbeitet - greift man auf denselben Speicherbereich zu, der bei der Arrayinitiierung dem Array zugewisen wurde. **ACHTUNG2:** \\ Der Operator **void** als Funktionsparameter bedeutet, dass die Funktion keine Parameter annimmt. \\ Kein Parameter bei einer Funktion bedeutet, dass die Funktion eine beliebige Anzahl von Parametern annimmt. \\ <sxh cpp> void noParamFunc(void){} //noParamsFunc(1) is illegal void anyParamFunc(){} // anyParamFunc(1) anyParamFunc("bla",21) is legal </sxh> == Operatoren == Operatoren sind Funtionen, die nicht in der //function()// Notation aufgerufen werden, sondern in der Infix, Postfix etc. Notation. <sxh cpp> //operatoren () [] -> . ! ~ ++ -- + - ( type ) * & sizeof new delete ->* .* * / % + - << >> < <= > >= == != & ^ , third operand ) , </sxh>

Operatoren können überladen werden. Das heisst den Operatoren kann man beibringen, wie man mit neuen Objekttypen umgeht.
Es können keine neuen Operatoren definiert werden wie z.B. ein Exponential-Operator “\*\*” oder ähnliches.

//so wird ein operator X überladen an dem k Zahlen beteiligt sind
RückgabeTyp operatorX(Def1, Def2, ..., Defk){}

//so wird ein operator + überladen fuer den eigens definierten Typ namens "complex"
complex operator+(complex& lhs, complex& rhs)
{
 complex Tmp;
 ...
 return Tmp;
}

Makefile

Makefiles ermöglichen die Automatisierung des Kompillier-Prozesses von mehreren Dateien inkl. der Auflösung von Abhängigkeiten.
In Makefiles definiert man Blockweise Dateien und Abhängigkeit ( Bibliotheken, Header Dateien ).
Zusätzlich werden die Befehle aufgeführt, die ausgeführt werden sollen, um die Abhängigkeiten aufzulösen.

Syntax:

//Makros
makro1 = .
makro2 = $(makro1)/code
makro3 = $(makro1)/sources
makro4 = $(makro1)/include
makro5 = $(makro1)/routines
makro6 = $(makro1)/lib

MAKRO_BINFILES = $(makro3)/ObjectFile.o
MAKRO_LIBFILES = $(makro3)/Y1.o $(makro3)/Y2.o $(makro3)/Y3.o
C++            = /usr/local/bin/gcc
MAKRO_BIND     = $(C++) $(LIBDIRS)


//block1
$(makro1)/BinaryZiel : $(MAKRO_BINFILES) $makro2/dependecy1.a
   $(MAKRO_BIND) -o $@ $(MAKRO_BINFILES) $(MAKRO_LIBFILES)
//block2
$(makro2)/dependecy1: $(MAKRO_LIBFILES)
....

Das Makro $@ gibt das aktuelle Ziel aus.
Das Makro $? gibt alle Abhängigkeiten des aktuellen Blockes aus, dessen Zeitstempel aelter als das Zeitstempel des Zeils ist.

Casting

| Value: | /cygdrive/d | D:\ |

















Summary

Eine Liste der wichtigen Momente, um Referenzen und Pointer zu verstehen:
Konzept Bezeichnung Erklärung Initiierung
TYPE& refName = varName Referenz Ist ein alias für eine Variable. Wird einmal und fuer immer initiiert. Wird mit Variablennamen initiiert, weil Referenz immer genau dasselbe bedeutet, wie dessen Ziel. Zusaetzlich ist eine explizite Referenz als Methodenparameter - die einzige Möglichkeit etwas “by reference” zu übergeben
&varName Adress-off Operator wenn man & vor einem variablennamen setzt - dann gibt der Ausdruck die Adresse der Variablen im Speicher zurück
TYPE* pointerName Pointer Ist ein pointer auf die Adresse der Variablen Wird mit der Adresse der Variablen initiiert.
*pointerName Dereferenz Operator wenn man * vor einem Pointernamen setzt - dann gibt der Ausdruck den Wert der Variablen zurueck, die im Speicher an der Stelle liegt, auf welche der Pointer zeigt.