Speicherverwaltung

Nein,

schau ein array hat mehrere Felder , doch das erste heisst nicht feld, sondern feld[0]. ISt ja auch logisch, deshalb hat feld[0] auch die Anfangsadresse. und feld wird nie Werte enthalten.
 
Wenn du also eine Integer Variable hast, welche auf einem "normalen" 32 Bit System normalerweise 2 Byte belegt..

Ein int hat normalerweise 4 Byte(32 Bit, damit hat auch die Architektur-Bezeichnung 32-Bit zu tun(Ein int hat afaik meistens die Größe eines (Standard-)Registers wie eax,edx,...))
Der Wertebereich ist daher von -2^31 bis 2^31-1.(editiert nach tr0nix Post)


Nicht wirklich: ary[0] ist die erste Variable im Array ary. ary zeigt auf ary[0](ary enthält die Adresse von ary[0]) also sind, wie ich erwähnt habe folgende Ausdrücke gleich:
Code:
foo = ary[0];
/*und*/
foo = *ary;
/*Und die Zeiger:*/
bar = ary;
bar = &(ary[0]);

*ary[0]
Der Inhalt der Adresse vom Inhalt der Adresse von ary[0];
Da keine Adresse enthalten, der direkte Inhalt von ary[0].

Leider auch nicht. Den Ausdruck *ary[0] nehmen die meisten Compiler nicht an, wenn ary ein Array vom Typ int ist. Grund: Du versucht hiermit eine Variable zu dereferenzieren(=als Adresse zu interpretieren und den Inhalt an dieser auszulesen), die kein Zeiger, sondern ein int ist. Wenn man dieses Verhalten so beabsichtigt müsste man das ganze noch typecasten. Normalerweise führt dieser Ausdruck dann aber zu einer segfault, da in dem Array in 90% der Fälle keine gültige Adresse steht. Zur Veranschaulichung mal ein kleines Programm:
Code:
#include <stdio.h>

int main(int argc,char **argv) 
{
	int i[1] = {0};
	int foo = *((int*)i[0]);
	return 0;
}

Führt man dieses aus, so stürzt es ab, da versucht wird auf die Adresse 0 zuzugreifen, die bei den meisten OSes ungültig ist:
In i[0] steht eine 0. Dann wird diese als Adresse interpretiert und es wird geschaut, was an der (virtuellen) Adresse 0 steht und das Programm stürzt wegen Zugriffsverletzung ab.
Oder umschrieben: Stell' Dir vor, du hast 10 Schubladen, nummeriert von 1-10 und in jeder liegt ein Zettel mit einer Zahl drauf. *ary[0] wäre jetzt, als würdest du die erste Schublade aufmachen und die Nummer auf dem Zettel(z.B. 157) als Schubladennummer interpretieren und schauen was in der Schublade dieser Nummer liegt. Da es keine Schublade mit der Nummer 157 gibt, stürzt das Programm ab.

Was sehr hilfreich zum Verständnis dieser Thematik ist, ist die Beschäftigung mit Assembly.

Ich hoffe, alle Klarheiten sind damit beseitigt. ;)
 
Zuletzt bearbeitet:
Ein int hat normalerweise 4 Byte(32 Bit, damit hat auch die Architektur-Bezeichnung 32-Bit zu tun(Ein int hat afaik meistens die Größe eines (Standard-)Registers wie eax,edx,...))
Der Wertebereich ist daher von -2^32 bis 2^32-1.
Hobbla 2! Umso besser wenn ich das ganze Zeugs mal wieder repetiere :).
 
Mir fällt gerade auf, dass ich aber bei dem Wertebereich Mist geschrieben habe: Da man ein Bit für das Vorzeichen benötigt, ist der Bereich von -2^31 bist 2^31 - 1.
 
So, einen habe ich dann noch ;)
wieseo ist bei:

int *zeig[2];
zeig[0]=10;
ungültige Umwandlung von »int« in »int*«

int *pnZahlen=new int[nAnzahl];
pnZahlen[0] = 10;
&pnZahlen[0]: 0x804c008 | pnZahlen[0]: 10
 
Nenenenene... wat machst du da bei deinem ersten Beispiel :). Du machst 2 Pointer du alloziierst nicht 2 Int! Du kannst nicht einfach einen Pointer machen und dort dann einen Wert zuweisen. Ein Pointer zeigt nachdem du ihn erstellt hast irgendwohin ins virtuelle Memory! Wenn deinem Prozess dieser Memorybereich nicht gehört und du arbeitest mit dem Pointer wirst du sehr wahrscheinlich einen Segfault kriegen oder das Programm wird seltsame Rückmeldungen geben.

Also entweder:
int zahl[2];
Oder:
int *zahl = new int[2];
 
Ja,
der Inhalt eines Pointers ist eine Adresse. Und erst in dieser ist ein Wert enthalten.
Doch gerade deshalb verwundert mich:

int *pnZahlen=new int[nAnzahl];
pnZahlen[0] = 10;
&pnZahlen[0]: 0x804c008 | pnZahlen[0]: 10


Denn das dürfte doch eigentlich nicht funktionieren.

--------------------------------------------------------------------------------------------
Ps:
Ich kann Nerven !!! :D
Ihr dachtet wohl Ihr seid mich los,
doch weit gefehlt, ich wurde nur am Woende aufgehallten! ;) :D :D ;)
:alkohol:
 
Doch natürlich. Nochmal:
int *zeiger; -> NUR ein Pointer, kein INT reserviert!
int zahl; -> Addressbereich mit 4 Byte für eine Zahl reserviert
int zahl[4]; -> Addressbereich 16 Byte für 4 Zahlen reserviert

Wenn du:
int *pnZahlen = new int[nAnzahl];
machst, ist das dasselbe wie:
int *pnZahlen;
int zahlen[nAnzahl];
pnZahlen = &zahlen;

Manchmal weisst du ja aber erst in einer Funktion, wieviel "Zahlen" du schlussendlich brauchst. In der Funktion selber dann aber "int zahlen[nAnzahl];" zu machen hilft dir ja nix weil du - sobald die Funktion beendet ist - das wieder verlieren würdest.

Deshalb machst du im globalen Bereich ein "int *zahlen" und in der Funktion wo du weisst, wieviele Zahlen du alloziieren musst ein "zahlen = new int[nAnzahl];".
 
Denn das dürfte doch eigentlich nicht funktionieren.

Dann hast du das Zeiger-Konzept immer noch nicht ganz verstanden. Aber mach dir keinen Kopf, bei mir hat es auch sehr lange gedauert bis ich es endgültig verstanden hab :) .

Code:
int *pnZahlen=new int[nAnzahl];
Du definierst hier einen Zeiger vom Typ int und weißt ihm ein dynamisch erzeugtes Array zu. pnZahlen zeigt nun auf das erste Element des Arrays, wodurch es sich wie ein statisches Array verhält. Du kannst also mit dem gewohnten Indizierungsoperator [] auf die einzelnen Array-Elemente zugreifen.

Code:
int *zeig[2];
Hier definierst du ein (2-elementiges) Array von Zeigern vom Typ int. Darauf kannst du auch per Indizierungsoperator [] zugreifen, allerdings kannst du kein int zuweisen, sondern nur ein Zeiger auf ein int. Richtig wäre also:
Code:
int zahl = 10;
int *zeig[2];
zeig[0] = &zahl;

Verstanden?

Gruß,
Philip
 
@SkydiverBS: vielen dank, deine Erklärung zu int *pnZahlen=new int[nAnzahl]; hat sehr geholfen.
Natürlich auch dir tr0nix ein herzliches Dankeschön.

zeiger können echt zum Horror werden! Verstanden habe ich es ja jetzt und es ist auch logisch, doch Sachen wie:
int *tmp;
tmp = ary;
tmp[1]=20;
obwohl zeiger nur Adressen haben dürfen, hierbei aber eine direkte weiterleitung zu ary[1] stattfindet ist wirklich gewöhnungsbedürftig.

Vielen Dank Euch das Ihr mich bei der genauern Erklärung von Zeigern so gut unterstützt habt!!! So genau findet man es in keinem Buch, oder ich habe keines von diesen gefunden.

gruß und viel Erfolg Euch allen noch
rdg
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Ok, sorry noch einmal, wirklich die letzte Frage,
warum geht bei einem Array:
int *tmp;
tmp = ary;
tmp[1]=20;
ich meine eigentlich dürfte es nicht und bei zeigern auf 1 dim. Variablen geht es ja auch nicht. Warum geht es dann bei Arrays?
 
Zuletzt bearbeitet:
Ok, sorry noch einmal, wirklich die letzte Frage,
warum geht bei einem Array:
int *tmp;
tmp = ary;
tmp[1]=20;

ich meine eigentlich dürfte es nicht und bei zeigern auf 1 dim. Variablen geht es ja auch nicht. Warum geht es dann bei Arrays?
Wenn ich dich richtig verstanden habe:

tmp ist zeigt nach deinem Beispiel (fett) auf ary (wobei ich mir nicht sicher bin, was ary ist oO; falls es ein Array sein sollte, so zeigt tmp auf den Anfang von ary).
Zeile 3 ist, so viel ich verstanden habe, dasselbe wie "ary[1] = 20".

Wie schon erwähnt, redest du etwas wirr (nimm's mir nicht übel), also nicht gleich aufessen, wenn ich dich falsch verstanden habe :P
 
genau und warum ist es zulässig anstatt:
ary[1] = 20;
tmp[1]=20 zu schreiben ?

Wenn ary (Abkürzung array) kein array sondern eine Variable wäre:
int var;
int *tmp;
tmp = var;
ergibt das einen Fehler, was auch richtig ist, da nur Adressen gespeichert werden dürfen.
 
Weil der Pointer nicht weiss, wieviel Elemente dort sind, wo du hinpointerst. Ich hab dir vorher mal erklärt, dass wenn ein Int 4 Byte ist und du gehst über einen Pointer auf ein Array Element, er nichts anderes macht als Addresse + n * sizeof(int). Wenn die daraus resultierende Addresse irgendwo im Speicher liegt ist deinem Programm das egal, es wird vielleicht crashen, aber es ist ihm egal :).
Wenn du solche Risiken nicht eingehen willst müsstest du am ehesten zu Java wechseln, ansonsten immer prüfen, ob der Arrayindex gültig ist.

int ary = 20; // Speicherplatz 0x00 - 0x03
int *pointer; // Speicherplatz 0x04
pointer = &ary;
pointer[1] = 5; // Jetzt greifst du auf den Speicherbereich 0x00 + 4 Bytes zu -> ausserhalb von "ary".

Dasselbe würde auch passieren wenn du auf ary[1] zugreifst (wenn der Compiler das erlaubt, wir haben ary ja nicht als Array definiert) da der Wert "20" sich ja an nullter Stelle (ary[0]) befindet.
 
Sorry, das ich Euch so genervt habe!
Ich wollte es endlich einmal richtig verstehen.
Deshalb vielen Dank an Euch ALLE! das Ihr Euch die Zeit und den Nerv für meine Fragen genommen habt!!
 
Macht doch nix dafür sind wir da! Zudem hab ihc ja auch wieder was gelernt dabei ;)
 
Vielen Dank Euch das Ihr mich bei der genauern Erklärung von Zeigern so gut unterstützt habt!!!

Gern geschehen :D !

So genau findet man es in keinem Buch, oder ich habe keines von diesen gefunden.

Das stimmt wohl. Dafür ist ein Forum ja auch da. Allerdings noch als Tipp: Wirf vielleicht mal einen Blick in das Buch "The C Programming Language" (oder die deutsche Version "Programmieren in C") von Brian W. Kernighan und Dennis M. Ritchie (dem Entwickler von C). Ich habe lange im Dunkeln getappt was Zeiger angeht. Ich wusste zwar grundsätzlich was Zeiger sind, aber es gab immer wieder Spezialfälle, wo ich nur durch probieren auf die richtige Lösung kam. Erst mit diesem Buch hat sich das geändert. Ich finde dort werden Zeiger sehr gut erklärt und auch gleich zu Beginn mit Arrays verglichen, so dass man später weiß wie man die beiden Sachen auseinander hält.

Gruß,
Philip
 
Ich wusste zwar grundsätzlich was Zeiger sind, aber es gab immer wieder Spezialfälle, wo ich nur durch probieren auf die richtige Lösung kam.
Genauso geht es mir auch, Ich hatte einfach keine Lust mehr zum abpausen und wollte es jetzt endlich richtig verstehen und in den Büchern hatte ich leider nur ungenügende Antworten gefunden. Das Buch was du mir empfohlen hast werde ich mal anschauen.

So, ich war nicht untätig, und habe meine Hilfsunterlagen in eine zip zusammengefügt. Nicht groß nicht ausergewöhnlich, doch finde ich sie gut und wollte deshalb jedem die Möglichkeit verschafffen sie zu benutzen. Musste nur leider meine Webseite dafür umbauen, weshalb es länger gedauert hat.
Also wenn Interesse:
http://rdg-web.de/web/linux-web/haupt.php?m=sachen&t=Download
bzw.
http://www.rdg-web.de/download/zeiger.zip

gruß und alles gute!
 

Ähnliche Themen

Fehler bei Zeigern ?

C Programm unter Unix

Modulfehler?

qt Anfängerprobleme

funktion threaden...

Zurück
Oben