Die Adresse, die an der Adresse steht auf die virtAddr zeigt, wird als
Zeiger auf int aufgefasst und dort (wegen der [0]) der Wert 1 abgelegt.
Der * von *virtAddr ist eine Dreferenzierung.
Das (int*) ist ein cast.
Die Definition von virtAddr sollte in der Art sein:
Typ **virtAddr;
virtAddr ist ein Pointer, der auf einen Pointer zeigt, in dem steht mit
welchem Speicher zu arbeiten ist
1
virtAddr
2
+--------+
3
| o---------------------+
4
+--------+ |
5
|
6
v
7
+----------+ +---------------+
8
| o--------------------->| eigentlicher |
9
+----------+ | Speicher- |
10
| Bereich |
11
| für |
12
| die Daten |
13
| |
14
+---------------+
es könnte zb sein, dass der mittlere Pointer einfach nur Teil eines
Arrays ist, indem die Pointer in den Speicher gesammelt werden und
mittels virtAddr wird einer dieser Pointer ausgewählt.
verfolge den Pfeil, der davon ausgeht. Du landest bei einem weiteren
Rechteck
1
(int*)*virtAddr
das was du dort in diesem Rechteck vorfindest, fasse es als Pointer auf
einen int auf.
1
((int*)*virtAdr)[0]=
verfolge den dort ausgehenden Pointer weiter und schreibe dort wo er
hinzeigt (wegen Array-Pointer Dualität) etwas rein (wobei du den
speicher als einen int auffasst)
Erdling schrieb:> Muß man das wirklich - aus meiner Sicht - so kompliziert gestalten?
Das ist doch nicht kompliziert.
Das ist das ganz normale Ergebnis, das rauskommt, wenn man eine Funktion
in die Lage versetzen will, beim Aufrufer eine Pointer Variable zu
verändern.
> Das zu verstehen ist'n zäher Brocken...
Das ist stink normales C. Willkommen in der 2-Stern Programmierung
Karl Heinz schrieb:> Das ist das ganz normale Ergebnis, das rauskommt, wenn man eine Funktion> in die Lage versetzen will, beim Aufrufer eine Pointer Variable zu> verändern.
Wie schreibst du das denn, wenn eine Funktion einen int beim Aufrufer
verändern soll?
Doch wohl so
1
voidfoo(int*pI)
2
{
3
*pI=6;
4
}
5
6
intmain()
7
{
8
intj;
9
10
foo(&j);// j kriegt von foo den Wert 6
11
}
Was ist das allgemeine Schema?
1
voidfoo(T*pointerToVariable)
2
{
3
*pointerToVariable=WertfürdieVariable;
4
}
5
6
intmain()
7
{
8
Tvariable;
9
10
foo(&variable);
11
}
und jetzt setzt du für T einfach mal einen Pointer Datentyp ein. Zb.
einen void *
Wenn in
1
void*virtSrcPage,*physSrcPage;
2
makeVirtPhysPage(&virtSrcPage,&physSrcPage);
die Funktion in der Lage sein soll, an virtSrcPage einen neuen Wert
zuzuweisen (weil die Funktion Speicher allokiert und die Adresse dieses
allokierten Speichers in virtSrcPage ablegen soll), dann muss die
Funktion einen Pointer auf die Pointer-Variable virtSrcPage kriegen.
Damit muss logischerweise das Funktionsargument ein void ** sein. Immer
1 * mehr als der Datentyp der Variablen, die sie verändern können soll.
Erdling schrieb:> Muß man das wirklich - aus meiner Sicht - so kompliziert gestalten?
Wenn man sich einige Zeit mit Pointern in C intensiv beschäftigt hat,
ist das überhaupt nicht mehr kompliziert. Den Code (den Du da oben
gepostet hast) liest sich dann genauso flüssig wie die Tageszeitung am
Morgen.
Bis dahin ist es aber ein harter weg.
Die doppelten Sternchen sind nur deshalb nötig, damit die Funktion die
eigentlichen Pointer, die übergeben werden, modifizieren kann. Denk Dir
erstmal überall ein Sternchen weg. Dann wird es einfacher.
> Das zu verstehen ist'n zäher Brocken...
Das lernt man nicht in ein paar Tagen.... mach Dir nichts draus. Es kann
auch mal Fälle mit 3 Sternchen hintereinander geben. Dann wirds wirklich
heftig. ;-)
Ich glaube dieses vereinfachte Beispiel:
>Was ist das allgemeine Schema?
1
voidfoo(T*pointerToVariable)
2
{
3
*pointerToVariable=WertfürdieVariable;
4
}
5
6
intmain()
7
{
8
Tvariable;
9
10
foo(&variable);
11
}
zusammen mit der Ziel WORUM es überhaupt geht:
>Wenn die Funktion in der Lage sein soll, an virtSrcPage einen neuen Wert>zuzuweisen (weil die Funktion Speicher allokiert und die Adresse dieses>allokierten Speichers in virtSrcPage ablegen soll), dann muss die>Funktion einen Pointer auf die Pointer-Variable virtSrcPage kriegen.
hat mir das Tor zum Verständnis geöffnet. Wenn man es versteht fühlt
sich der Aha!-Effekt nämlich besonders gut an...
Danke für die Mühe.
Frank M. schrieb:> Mark Brandis schrieb:>> Hast Du ein ASCII-Malprogramm dafür? Auch haben will :-)>> Hat jeder, so ein ASCII-Malprogramm nennt sich Text-Editor. ;-)
Ich halte es zwar für durchaus denkbar, daß Karl Heinz die Bilder von
Hand im Editor malt, aber für Faulpelze wie mich gibts: AACircuit unter
http://www.tech-chat.de/download.html
ich liebe es:
zeiger die auf zeiger zeigen->
->die auf zeiger zeigen
->die auf zeiger zeigen
->die auf zeiger zeigen
->die auf zeiger zeigen....
das kenn ich zur genüge. nicht c ist schuld sondern der progger.
erinnert mich sehr stark an "objekt orientierten assembler" (borland?)
alle haben es gefordert.
irgendwann kam dann aus der entwicklung:"wer assembler objektorientiert
programmiert ist pervers..." und man würde sich über das beispiel einer
funktionoerden applikaton freuen.
c ist halt das werkzeug, das nicht belehrbare psychotiker zu ihren
programm-konstrukten (ohne kommentare!) motiviert.
und ich bewundere progger die da "add hoc2 noch einen sinn erkennen (so
er denn eindeutig ist...)
nur mal so frust ablassend (its my daily work)
Bitflüsterer schrieb:> Frank M. schrieb:>> Mark Brandis schrieb:>>> Hast Du ein ASCII-Malprogramm dafür? Auch haben will :-)>>>> Hat jeder, so ein ASCII-Malprogramm nennt sich Text-Editor. ;-)>> Ich halte es zwar für durchaus denkbar, daß Karl Heinz die Bilder von> Hand im Editor malt
Tue ich.
Wenn man das Bild im Kopf hat, das entstehen soll, geht das relativ
schnell.
Karl Heinz schrieb:> Bitflüsterer schrieb:>> Frank M. schrieb:>>> Mark Brandis schrieb:>>>> Hast Du ein ASCII-Malprogramm dafür? Auch haben will :-)>>>>>> Hat jeder, so ein ASCII-Malprogramm nennt sich Text-Editor. ;-)>>>> Ich halte es zwar für durchaus denkbar, daß Karl Heinz die Bilder von>> Hand im Editor malt>> Tue ich.> Wenn man das Bild im Kopf hat, das entstehen soll, geht das relativ> schnell.
Äh. Nein? Das Problem ist ja das Einfügen von Elementen, was jedes
andere Element in der gleichen Zeile nach hinten verschiebt.
Also wenn man das von Anfang an richtig im Kopf hat und perfekt
hinzimmert - dann meinen Respekt. Das krieg ich so nicht hin.
Mark Brandis schrieb:> Äh. Nein? Das Problem ist ja das Einfügen von Elementen, was jedes> andere Element in der gleichen Zeile nach hinten verschiebt.
Dafür gibt's - seit den Anfängen der IT - die "Insert"-Taste, die
zwischen Einfügen und überschreiben umschaltet...
Markus F. schrieb:> Dafür gibt's - seit den Anfängen der IT - die "Insert"-Taste, die> zwischen Einfügen und überschreiben umschaltet...
Ach wer benutzt die schon ;-)
Markus F. schrieb:> Dafür gibt's - seit den Anfängen der IT - die "Insert"-Taste, die> zwischen Einfügen und überschreiben umschaltet...
... aber leider in der Regel das Entfernen nicht entsprechend mit
umschaltet. Also ich tippe irgendwo ein Zeichen rein, und alles danach
bleibt, wie es ist und verschiebt sich nicht. Ich lösche das Zeichen
wieder, weil an der falschen Stelle, und alles verschiebt sich. Ich will
dafür ein Leerzeichen einfügen, was aber stattdessen das nächste Zeichen
auch noch mit was falschem überschreibt, weil ich erst wieder auf
einfügen hätte umschalten müssen. Das hat mich schon einiges an Nerven
gekostet. ;-)
c-lover schrieb:> ich liebe es:> zeiger die auf zeiger zeigen->> ->die auf zeiger zeigen> ->die auf zeiger zeigen> ->die auf zeiger zeigen> ->die auf zeiger zeigen....> das kenn ich zur genüge. nicht c ist schuld sondern der progger.
Wie würdest du das denn machen? Wenn man aus eine Funktion etwas über
einen Parameter rausgeben will, macht man einen Zeiger darauf. Wenn das,
was man rausgibt, auch schon ein Zeiger ist, ergibt sich logischerweise
ein Zeiger auf einen Zeiger.
> c ist halt das werkzeug, das nicht belehrbare psychotiker zu ihren> programm-konstrukten (ohne kommentare!) motiviert.
Wer sich "progger" nennt, und die Großmachtaste nicht findet, sollte
nicht so große Töne spucken.
c-lover schrieb:> ich liebe es:> zeiger die auf zeiger zeigen->> ->die auf zeiger zeigen> ->die auf zeiger zeigen> ->die auf zeiger zeigen> ->die auf zeiger zeigen....> das kenn ich zur genüge. nicht c ist schuld sondern der progger.
Sowas kommt doch dauernd vor, verkettete Liste z.B.
Verkehrt in C ist die Syntax, wie man Variablen, vor allem Pointer,
deklariert (Zeiger auf Funktion, die einen Zeiger auf ein Array aus
Funktionszeigern mit selber Signatur returniert?).
Hirnrissig wirds dann beim Derefenzieren von (mehreren) Pointern, das
schreibt sich in Pascal z.B. viel verständlicher. Das haben auch die
Schöpfer der Go-Sprache erkannt (die teilweise ja auch C aus den Windeln
geholfen haben), und dort die Syntax repariert:
http://blog.golang.org/gos-declaration-syntax
Bei Exzessivem *-Gebrauch wird man von bösen Zungen auch Zweistern- oder
Dreistern-Programmierer geschimpft
(http://c2.com/cgi/wiki?ThreeStarProgrammer).
Rufus Τ. Firefly schrieb:> rmu schrieb:>> Verkehrt in C ist die Syntax>> Vielleicht nicht "verkehrt", sondern Dir unverständlich?
Unverständlich nicht, aber trotzdem verkehrt, wie in "die Reihenfolge
stimmt nicht", auf mehreren Ebenen.
Intuitiv wäre m.E. das pascal-artige "lass p einen Zeiger auf int sein"
und nicht das C-artige "lass int den Typ sein, der beim Derefenzieren
von p herauskommt".
In manchen Coding Conventions wird "verboten", sowas wie
1
int *p, i;
zu schreiben, sondern verlangen
1
int* p; // pointer: stern beim Typ, eigene Zeile notwendig
2
int i;
mit dem Stern (oder in C++ auch das & für Referenz) beim Typ.
rmu schrieb:> Sowas kommt doch dauernd vor, verkettete Liste z.B.>> Verkehrt in C ist die Syntax, wie man Variablen, vor allem Pointer,> deklariert (Zeiger auf Funktion, die einen Zeiger auf ein Array aus> Funktionszeigern mit selber Signatur returniert?).
Paradebeispiel für schwer verständliche Deklarationen ist die
Standard-Funktion signal():
1
void(*signal(intsig,void(*handler)(int)))(int);
Aber das läßt sich recht leicht entschärfen:
1
typedefvoid(*sighandler_t)(int);
2
sighandler_tsignal(intsig,sighandler_thandler);
rmu schrieb:> Intuitiv wäre m.E. das pascal-artige "lass p einen Zeiger auf int sein"> und nicht das C-artige "lass int den Typ sein, der beim Derefenzieren> von p herauskommt".
Diese verdrehte Logik bei der Deklaraton in C fand ich auch schon immer
eher unglücklich. Urspügnlich war das ja geacht, um's intuitiver zu
machen, aber das ist meines Erachtens nach hinten losgegangen.
Rolf Magnus schrieb:> rmu schrieb:>> Intuitiv wäre m.E. das pascal-artige "lass p einen Zeiger auf int sein">> und nicht das C-artige "lass int den Typ sein, der beim Derefenzieren>> von p herauskommt".>> Diese verdrehte Logik bei der Deklaraton in C fand ich auch schon immer> eher unglücklich. Ursprünglich war das ja gedacht, um's intuitiver zu> machen, aber das ist meines Erachtens nach hinten losgegangen.
Ich denke eher, dass das eine Folge einer Optimierung des Compilers war,
da sich so der Ausdruck-Parser auch für die Variablen-und
Typ-Deklarationen missbrauchen lässt. Das ist ja auf einem Rechner
entstanden, der 64k 18bit-Worte RAM Maximalausbau hatte.
Wenn man mit Funktionszeigern jongliert kann man gar nicht genug
typedefs verwenden, das hilft definitiv, sonst wirds wie bei der
signal-decl oben schnell mal unklar, wo man welchen Namen hinschreibt,
und wie der resultierende Typ dann eigentlich heisst.
Zum Glück wurde der "->" Operator vorgesehen, man stelle sich vor, was
man sonst für Konvolute aus verklammerten * und . schreiben müsste...
Ansonsten seh ich das recht fatalistisch, man kann nix ändern daran,
verschwinden wird C auch nicht, und schliesslich gewöhnt man sich
irgendwann eh an alles... ;-)
Um auch was sinnvolles beizutragen, hier
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html gibts die Geschichte
von C aus der Sicht von Dennis M. Ritchie.
rmu schrieb:> Rolf Magnus schrieb:>>> Diese verdrehte Logik bei der Deklaraton in C fand ich auch schon immer>> eher unglücklich. Ursprünglich war das ja gedacht, um's intuitiver zu>> machen, aber das ist meines Erachtens nach hinten losgegangen.>> Ich denke eher, dass das eine Folge einer Optimierung des Compilers war,> da sich so der Ausdruck-Parser auch für die Variablen-und> Typ-Deklarationen missbrauchen lässt. Das ist ja auf einem Rechner> entstanden, der 64k 18bit-Worte RAM Maximalausbau hatte.
Denke ich eher nicht.
Denn bei Casts musst du die Datentypen ohne den Variablennamen an der
richtigen Stelle parsen.
Casts gabs auch bei K&R C schon.