Anfängerfrage zu Zeigern - bitte nicht hauen ;-)

Kümmelkorn

Aktives Mitglied
Thread Starter
Dabei seit
06.10.2008
Beiträge
1.941
Reaktionspunkte
127
Hallo,

es ist mir fast schon peinlich, die Frage zu stellen, aber es verwirrt mich total:

Die Regel, die man in Tutorials so eingedröhnt bekommt, ist: Ein Zeiger zeigt auf die Adresse der Variable (die ihm mit pointer = &variable zugewiesen wurde). Ok, das ist ja nicht schwer - aber was ist, wenn dem Zeiger gar keine Variable zugewiesen wurde, wie es bei dem "Erzeugen" eines Objekts der Fall ist? Beispiel:

Code:
// Das da ist Objective-C Code.. wahrscheinlich überflüssig zu erwähnen...
NSString *meinString = @"Hallo Welt";

Hier habe ich dem Zeiger nunmal nichts zugewiesen, was eine Adresse hat! Ein Text hat ja schlecht eine Adresse!? Trotzdem funktioniert es, und irgendwie hat der Text dann doch eine Adresse - ich kann sie mir sogar ausgeben lassen... aber wie kann denn Text eine Adresse haben, ich dachte, nur Variablen und Objekte können Speicheradressen haben? Der Text kann aber kein Objekt sein, weil ich nie ein Objekt erzeugt habe, sondern nur einen komischen Zeiger auf einen Text...

Irgendwie ist das komisch ... :mad:

--
Forge
 
Zuletzt bearbeitet:
die strings aus der source werden doch auch gespeichert, die werden ja nicht aus der luft geholt...
 
mh... na gut... stimmt auch wieder... und warum muss ich, wenn NSStrings Objekte sind, diese nicht wie fast alle anderen Objekte mit alloc und init erzeugen? Woher weiß man eigentlich bei Klassen, die man nicht selbst geschrieben hat, ob man alloc und init nutzen muss oder nicht?
 
Hier habe ich dem Zeiger nunmal nichts zugewiesen, was eine Adresse hat! Ein Text hat ja schlecht eine Adresse!?
Selbstverständlich!

Dieses Objekt wird konstant auf dem Stack angelegt. Dass es kein C-String ist, erkennt man an dem "@".

Woher weiß man eigentlich bei Klassen, die man nicht selbst geschrieben hat, ob man alloc und init nutzen muss oder nicht?

Ich verstehe die Frage nicht

Alex
 
mh... na gut... stimmt auch wieder... und warum muss ich, wenn NSStrings Objekte sind, diese nicht wie fast alle anderen Objekte mit alloc und init erzeugen?

weil die dann nur gekapselt sind im objekt...
und deren inhalt wird ja nicht dynamisch erzeugt...

Woher weiß man eigentlich bei Klassen, die man nicht selbst geschrieben hat, ob man alloc und init nutzen muss oder nicht?

das geschieht doch automatisch.
die init methode wird doch geerbt und erweitert für das vorliegende objekt...
wenn du ein objekt instanziierst, wird init aufgerufen...
 
Hi Forge,

jedes Programm hat drei Speicherbereiche, auch Segmente genannt.
Das wäre das Code-Segment, das Daten-Segment und der Stack.

Auf den Inhalt aller drei Speicherbereiche kann man mit einem Pointer zeigen. Wobei ich jetzt nicht weiß, ob es in C bzw. Objective-C ein Sprachkonstrukt gibt, mit dem du auf das Code-Segment zeigen kannst.
Für das Daten-Segment und den Stack geht das auf jeden Fall.

Im Code-Segment landet dein von dir geschriebener und kompilierter Code. Um auf die Befehle im Code-Segment zu zeigen, gibt es AFAIK nur den Instruction-Pointer (IP). Ich will jetzt nicht zu weit abschweifen, aber das ist ein Register vom Prozessor, damit der Prozessor weiß, welchen Befehl er als nächstes abarbeiten soll.

Im Daten-Segment wird der Speicher reserviert, den man per sich z.B. in C per malloc() holt. Ich bin mir jetzt nicht sicher, aber ich meine, daß in C++ und Objective-C alle Objekte im Datensegment landen. Je nach Programmiersprache und Implementierung werden hier auch Konstanten und globale Variablen abgelegt.

Dann gibt es noch den Stack. In diesem werden Funktions-Parameter, lokale Variablen und Funktions-Rücksprung-Adressen abgelegt. Ebenfalls Programmiersprachen- und Implementierungsabhängig landen auf dem Stack noch die Rückgabewerte von Funktionen.

Z.B.
Code:
function void rammstein(int x) {
     char[] msg1 = "Ja das ist mein Teil";
     char[] msg2 = malloc(x);
     // Tu was
     return;
}

Wenn man jetzt die Funktion aufruft
Code:
rammstein(9);
dann wird zu erst die 9 auf den Stack geschrieben. Danach die Rücksprungadresse, also der Wert den der IP gerade hat, damit man nachdem rammstein() abgearbeitet wurde, wieder an der Stelle landet, wo man rammstein() aufgerufen hat.

Wenn dann in die Funktion rammstein() gesprungen wird, wird erst mal "Ja das ist mein Teil" auf dem Stack gespeichert. msg1 enthält jetzt die Adresse vom Stack, an der das "J" steht.
Danach wird von malloc() Speicher vom Datensegment reserviert. In diesem Beispiel sind das 9 Bytes. msg2 Zeigt auf das erste dieser 9 Bytes.

Da msg1 und msg2 für den Programmierer gleich aussehen, ist es etwas problematisch um zwischen Pointern auf dem Stack und auf dem Daten-Segment zu unterscheiden. Intern regelt das jedoch der Compiler.


So. Hab jetzt weit ausgeholt, um deine Frage zu beantworten.
Code:
@"Hallo Welt"
ist ein Objekt von Type NSString und wird zur Laufzeit auf dem Daten-Segment abgelegt. In meinString landet die Speicher-Adresse an der das Objekt zu finden ist.


Gruß Fabian
 
und warum muss ich, wenn NSStrings Objekte sind, diese nicht wie fast alle anderen Objekte mit alloc und init erzeugen?

Du kannst auch das. Aber weil Strings so oft vorkommen, sind sie als kurzschreibweise eingebaut. Außerdem kann immer wieder das gleiche Objekt benutzt. Du kannst natürlich auch:

Code:
NSString *meinString = [[NSString alloc] initWithUTF8String: "Hallo Welt"];

Woher weiß man eigentlich bei Klassen, die man nicht selbst geschrieben hat, ob man alloc und init nutzen muss oder nicht?

Wenn du das Objekt erzeugst, musst du immer alloc und init benutzen. Wenn eine Klassenfunktion das Objekt für dich erzeugt, dann musst du retain benutzen, um es zu behalten.

Code:
NSString *meinString = [[NSString stringWithUTF8String: "Hallo Welt"] retain];
 
Im Daten-Segment wird der Speicher reserviert, den man per sich z.B. in C per malloc() holt. Ich bin mir jetzt nicht sicher, aber ich meine, daß in C++ und Objective-C alle Objekte im Datensegment landen.
In C++ nur, wenn man sie mit new erstellt.
 
Hallo,

es ist mir fast schon peinlich, die Frage zu stellen, aber es verwirrt mich total:

Die Regel, die man in Tutorials so eingedröhnt bekommt, ist: Ein Zeiger zeigt auf die Adresse der Variable (die ihm mit pointer = &variable zugewiesen wurde). Ok, das ist ja nicht schwer - aber was ist, wenn dem Zeiger gar keine Variable zugewiesen wurde, wie es bei dem "Erzeugen" eines Objekts der Fall ist? Beispiel:

Code:
// Das da ist Objective-C Code.. wahrscheinlich überflüssig zu erwähnen...
NSString *meinString = @"Hallo Welt";

Hier habe ich dem Zeiger nunmal nichts zugewiesen, was eine Adresse hat! Ein Text hat ja schlecht eine Adresse!? Trotzdem funktioniert es, und irgendwie hat der Text dann doch eine Adresse - ich kann sie mir sogar ausgeben lassen... aber wie kann denn Text eine Adresse haben, ich dachte, nur Variablen und Objekte können Speicheradressen haben? Der Text kann aber kein Objekt sein, weil ich nie ein Objekt erzeugt habe, sondern nur einen komischen Zeiger auf einen Text...

Irgendwie ist das komisch ... :mad:

--
Forge
Um es vollständig zu machen:

Der Compiler erzeugt bei der Übersetzung eine Struktur der Art:
Class isa
char* string
int length

oder so ähnlich. Für jeden String speichert er das im Objectktfile. Zur Ladezeit werden alle Strings durchsucht und isa durch die Standardklasse für alle konstanten Strings ersetzt. Die kann man übrigens einstellen.

Du hast also ein konstantes String-Objekt, keinen einfachen Werteskalar wie 5 oder 6.89.Mutmaßlich ist dir das aufgestoßen, weil ja auch nicht int* a = &5; geht. Aber es ist eben etwas anderes.
 
mh... na gut... stimmt auch wieder... und warum muss ich, wenn NSStrings Objekte sind, diese nicht wie fast alle anderen Objekte mit alloc und init erzeugen?
Die Objekte werden wie untern beschrieben vom Compiler vorbereitet. Sie haben bereits Speicher, weshalb +alloc entfällt und sie werden vomLader gesetzt, weshalb -init… entfällt. Die einzig verbleibende Aufgabe des isa wird ebenfalls vom Lader übernommen, siehe unten. Genau genommen ist dieses Objekt zuerst initialisiert und dann ein Objekt. Schon komisch, da hast du Recht.

Woher weiß man eigentlich bei Klassen, die man nicht selbst geschrieben hat, ob man alloc und init nutzen muss oder nicht?
Man muss oder eine Methode die das für einen macht (new odermit -autorelease ein CA)
 
Zurück
Oben Unten