Beispiel mit Zeigern - einige Fragen

Schnelle objektorientierte, kompilierende Programmiersprache.
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Beispiel mit Zeigern - einige Fragen

Beitrag von Xin » Mi Mär 12, 2014 12:57 pm

Dann will ich auch mal flott Stellung beziehen.
Ich bin gerade etwas überrascht bzgl. der Menge der Kritik. Aber positiv überrascht.
@forumnewbie: Da ist doch eine Menge zusammengekommen, was ich mir ausdrucken und Schritt für Schritt abarbeiten muss.

@mfro: Zu const bzw. readonly stimme ich Dir soweit zu, dass es hier semantische Unterschiede gibt bzgl. dessen, was damit gemacht wird. Auf abstrakter Ebene muss mich aber nicht interessieren, ob in welchem Codesegment die Daten ankommen oder welche Typen von Segmenten das Executable-Format besitzt. Hier reicht es vollkommen zu verstehen, dass dieser Datentyp innerhalb meines Scopes für von mir unveränderlich ist. Ich werde mir das aber unter diesem Gesichtspunkt auch nochmal durchlesen und ich bin sicher, dass ich dies im Hinterkopf noch Aussagen verbessern kann.

Fehler, die beim Linken geschehen wären allerdings eher ein Fortgeschrittenen-Artikel, denn das Linken gehört prinzipiell nicht zur Sprache C, sondern ist davon abgehoben - es gilt schließlich genauso zu C++, Pascal, Purebasic, und vielen anderen Sprachen.
Hier würde ich mir mal ein Step-By-Step-Tutorial vom Quelltext zum ausführbaren Programm wünschen, bei dem jeder Arbeitsschritt einzeln gemacht wird und anschließend mit objdump etc. das Executable bzw. die Library wieder auseinander genommen wird, was vom abstrakten Code am Ende wirklich übrig geblieben ist.
Die Baustelle möchte ich aber jetzt nicht aufmachen. ^^
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Beispiel mit Zeigern - einige Fragen

Beitrag von mfro » Mi Mär 12, 2014 1:10 pm

Xin hat geschrieben: @mfro: Zu const bzw. readonly stimme ich Dir soweit zu, dass es hier semantische Unterschiede gibt bzgl. dessen, was damit gemacht wird. Auf abstrakter Ebene muss mich aber nicht interessieren, ob in welchem Codesegment die Daten ankommen oder welche Typen von Segmenten das Executable-Format besitzt.
Klar.

Nur ganz kurz: wie würdest Du die Frage beantworten, was um Himmels Willen (z.B.) ein const volatile int (const = konstant, volatile = veränderlich, unbeständig, wörtlich also eine "konstante Veränderliche") sein soll und wozu man das wohl gebrauchen kann (übrigens gibt es dafür sehr sinnvolle Verwendungen)?

Läßt sich m.E. am einfachsten erklären, wenn man den "Unfall" const <-> readonly erklärt. Es kann ja auch mal was schief gehen, bei so einer Sprachdefinition ;).
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Beispiel mit Zeigern - einige Fragen

Beitrag von Xin » Mi Mär 12, 2014 2:02 pm

mfro hat geschrieben:Nur ganz kurz: wie würdest Du die Frage beantworten, was um Himmels Willen (z.B.) ein const volatile int (const = konstant, volatile = veränderlich, unbeständig, wörtlich also eine "konstante Veränderliche") sein soll und wozu man das wohl gebrauchen kann (übrigens gibt es dafür sehr sinnvolle Verwendungen)?
Volatile bedeutet vorrangig, dass der Wert nicht im CPU-Register zwischengespeichert werden darf, weil er von außerhalb verändert werden könnte.
const bedeutet vorrangig, dass ich ihn nicht ändern darf. Hier wäre "readonly" sicherlich das semantisch naheliegendere Schlüsselwort, aber ich verstehe auch, dass man eine Sprache bzgl. der Keywords möglichst klein halten möchte und const bei "const int i=0" schon vorhanden war.
Da ich selbst an einer Sprache frickle, kommt für mich noch ein Punkt dazu: Eine Balance zwischen leichter Lesbarkeit und Länge der sprachlichen Mittel. "readonly" ist ein vergleichsweise langes Wort, "ro" ist schnell mit anderen temporären Variablen zu verwechseln, z.B. "rechts oben". "const" heißt ja auch nicht "constant".

C ist bewusst sehr klein gehalten worden. Ich persönlich hätte "unsigned" als default für alle Integers genommen und sogar das Schlüsselwort noch eliminiert.
mfro hat geschrieben:Läßt sich m.E. am einfachsten erklären, wenn man den "Unfall" const <-> readonly erklärt. Es kann ja auch mal was schief gehen, bei so einer Sprachdefinition ;).
Ich denke, ich werde das aufgreifen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: Beispiel mit Zeigern - einige Fragen

Beitrag von oenone » Do Mär 13, 2014 11:33 am

In C# gibt es tatsächlich ein "readonly" Schlüsselwort für Laufzeitkonstanten, in etwa mit dem "final" Schlüsselwort von Java vergleichbar.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Feedback Teil 1

Beitrag von Xin » Mo Mär 17, 2014 11:03 pm

forumnewbie hat geschrieben:Dann fange ich mal an. Zunächst Arrays + Strings. (Mit "Lob" meinte ich die Stellen, die BESONDERS gut zum Verständnis beitragen, was nicht bedeutet, dass andere Stellen schlecht sind :) )
Etwas Zeit... mal gucken wie weit wir kommen.
forumnewbie hat geschrieben:
Hier haben wir also einen Identifier eins vom Typ int und einen Identifier vier vom Typ int[4], vier ist also viermal so groß wie eins.
In den eckigen Klammern wird wieder ein Expression des Typs Integer erwartet.
Wenn man auf einen englischen Begriff verzichten kann, bitte diesen durch einen deutschen Begriff ersetzen oder am Anfang irgendwo erklären was das genau ist/heißt
Glossary-Links gesetzt.
forumnewbie hat geschrieben:
int object = array[ 17 ]
In den eckigen Klammern wird wieder ein Expression des Typs Integer erwartet. Übergeben wird ein Index und dieser muss ja abzählbar sein. Dass es ein Expression ist bedeutet, dass wir eine Konstante, wie in diesem Beispiel 17, angeben können, eine Variable, wie i im Beispiel zuvor oder auch eine Formel beliebiger Länge zur Berechnung des Indexes wird akzeptiert:
Ich finde - kompliziert geschrieben. Du meinst, wir weisen einfach der Variable objekt einen Wert mit der Index 17 aus dem Vektor array zu?
Expression habe ich ebenfalls mit Glossary verlinkt.

:-D. Ja. Ich habe den Abschnitt verändert.
forumnewbie hat geschrieben:Beim Wort Array würde ich auch einen Bezug zur Mathematik herstellen und sagen, dass ein Array nichts anderes als ein Vektor, bzw. Matrix/Tabelle mit 1 Spalte und n Zeilen oder 1 Zeile und n Spalten ist. Dann hat man sofort ein Bild im Kopf, weil man das schon x mal auf dem Taschenrechner benutzt hat. Und wenn nicht, dann kann sich jeder eine Tabelle mit Daten bestimmt vorstellen.
Ein Array ist aber keine Matrix. Die Geschichte mit mathematischen Vektor kommt schon eher wieder hin, da der Kurs aber auch mit Hilfe von einem 12jährigen verstanden werden soll, kann ich nicht Mathematik aus der...11. Klasse? nutzen, um hier eine abstrakte Idee vorzustellen.
Also zeichne ich die Tabelle.
forumnewbie hat geschrieben:
Nehmen wir nun an, dass wir ein sehr großes Array haben, dass es einfach zuviel Aufwand macht, es so zu initialisieren. Wir wissen ja bereits, dass sich C um die Initialisierung von Variablen nicht kümmert, also kümmert es sich auch nicht um die Initialisierung von vielen Variablen. Auch hier müssen wir also selbst ran und hierfür bietet sich natürlich eine Schleife an:
Warum muss ein Array in einer Schleife vorher mit Nullen initialisiert werden? Kann man es nicht später mit verschiedenen Werten initialisieren, wenn wir diese auch brauchen?
Kann man... aber woher weiß man dann, ob ein Wert gesetzt wurde?
Ich habe hier einen Satz erweitert.
forumnewbie hat geschrieben:Lob: Tabelle "Wie funktioniert ein Arrays" mit Erklärung ist sehr gut!
:-)
forumnewbie hat geschrieben:
Mit sizeof kann man auch die Größe eines Arrays in Arrays bestimmmen.
Wie ist das gemeint mit "Arrays in Arrays"?
Sehr gut, das ist ein Fehler: Wenn man wissen möchte, wie groß ein Array in Bytes ist!
forumnewbie hat geschrieben:
Wenn man wissen möchte, wie groß ein Array ist, muss man allerdings die Größe des Datentypes mit verrechnen.
Meinst du du hier die Anzahl der Elemente in einem Array und nicht die Größe des Arrays (bezogen auf dein Beispiel)?
Auch hier habe ich den Text angepasst.

=1358006247&rev2[1]=&difftype=sidebyside]Alle Änderungen auf der Array-Seite entsprechend dieser Kritik
forumnewbie hat geschrieben:Strings
http://www.proggen.org/doku.php?id=c:tutorial:cstrings
for( i = 0; text; i = i + 1 )

text vielleicht in text!=0 ändern, da man sonst eventuell die Abbruchbedingung nicht versteht
und i = i+1 in i++ ändern. Könnte einen Anfänger verwirren, da in der Literatur der Zählschritt/Anweisung mit ++ in der for-Schleife gemacht wird.

i++ haben die Leute an der Stelle noch nicht gelernt.

text haben sie gelernt, aber man kann ja nochmal dran erinnern.

forumnewbie hat geschrieben:
Für den Compiler spielt es keine Rolle, ob Du 0 oder '\0' schreibst, in beiden Fällen wird ein char mit 0 beschrieben.

Eventuell dazu schreiben, dass wenn man aber '0' schreibt die Zahl NULL im Text erscheint.
Laut ASCII steht dez 0 für das Zeichen NUL^@. NUL^@ entspricht dann dem Zeichen \0 ? Warum steht in der Tabelle nicht einfach \0?

Das schreibt jede Tabelle anders. Die einen schreiben NULL, die nächsten NUL, weil es drei Buchstaben hat, genau wie NIL, was man auch schonmal findet.
In C schreibt man es '\0', aber ASCII-Tabellen sind nicht nur für C gültig.

forumnewbie hat geschrieben:
while( text[length] )
length = length + 1;

Die Schleife wird abgebrochen, sobald das Zeichen \0 gefunden wird, weil wir als Rückgabewert beim text[length] kein Zeichen sondern eine Dezimalzahl 0 zurückbekommen, und somit die Abbruchbedingung erfühlt ist. Richtig?

Richtig.

forumnewbie hat geschrieben:Ich würde diesen Zusammenhang mit der Schleife und Zeichen \0 => dez 0 an dieser Stelle nochmal erwähnen, dh die Logik in den Beispielen an schwierigen Stellen mit 1-2 Sätzen näher erläutern. Für einen Anfänger ist das nicht sofort klar, wenn überhaupt.

Habe ich am ersten Beispiel gemacht.

forumnewbie hat geschrieben:Lob: Einzelne Zeichen suchen und austauschen - ein super Beispiel!
Lob ist immer gut :-)
forumnewbie hat geschrieben:So, nun brauche ich eine Pause :) Hoffe, dass ich bei meinem Feedback kein Blödsinn geschrieben habe - manchmal passiert das, wenn man zu lange auf den Monitor starrt :)

Nein, bisher war das super. Die Kritik ist gut beschrieben und nachvollziehbar. Wenn man so ein Tutorial schreibt, fallen einem manche Dinge nicht mehr auf, weil es für einen selbst ja selbstverständlich ist.

forumnewbie hat geschrieben:Was Bücher angeht - da bin ich einer anderen Meinung. Mir haben sie am Anfang trotzdem sehr geholfen - auch wenn sie leider nicht perfekt sind. Tutorials sind im Vergleich zu den Büchern deutlich kürzer - was nicht schlecht sein muss. Tutorials sind meiner Meinung nach für Benutzer mit Grundkenntnissen geeignet, für blutigen Anfänger sind aber Bücher besser - da man dort Sachen am Anfang viel ausführlicher behandelt und mehrmals wiederholt.

Das kann richtig sein. Allerdings erwarte ich von den Leuten tatsächlich, dass sie sich mit dem Stoff auseinander setzen und rumprobieren. Hier muss ich allerdings noch ein paar zusätzliche Aufgaben stellen, weil den Anfängern häufig die Fantasie dazu fehlt, sich selbst Fragen und Aufgaben zu stellen.

forumnewbie hat geschrieben:Ein Vorschlag: Eure Tutorials könnte man noch besser machen, wenn man nach jedem Tutorial mehrere Aufgaben dazu gibt, die ein Leser selbständig versuchen kann zu lösen. Und natürlich Lösungen dazu wenn man nicht weiterkommt und für den Vergleich.

Naums arbeitet da bereits an einer Trainings-Sektion, die ich auch bald mal verlinken muss.

Hier wieder die =1357161067&rev2[1]=&difftype=sidebyside]Änderungen zur Seite mit den Strings.

Auch wenn es oft etwas dauerte, bis ich die Kritik angegangen bin - dafür habe ich die Todo-Liste. Deine Arbeit gerät nicht einfach in Vergessenheit, ich muss nur selbst auch mal Zeit dafür haben. ^^
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Beispiel mit Zeigern - einige Fragen

Beitrag von Xin » So Mär 30, 2014 4:47 pm

forumnewbie hat geschrieben:So, hier der versprochene Teil 2. War fleißig :)
Zeiger
http://www.proggen.org/doku.php?id=c:tutorial:pointer

Kann ich statt NULL einfach 0 benutzen und das würde das selbe bedeuten? Dann könnte ich über #define NULL 0 auch ohne Standardbibliothek auskommen?
Ja, könntest Du, aber 0 bedeutet erstmal die Zahl 0. NULL bedeutet Null-Pointer. Diese Unterscheidung ist einem zwischen dem Wert 0 und dem ungültigen Zeiger ist C++ in der aktuellen Version ein eigenes Schlüsselwort wert: nullptr.
forumnewbie hat geschrieben:Welcher Zusammenhang besteht zwischen EXIT_SUCCESS und einem Zeiger? Zuvor steht Erklärung zum NULL Zeiger gefolgt von einem Doppelpunkt und dann plötzlich EXIT_SUCCESS.
Keiner. Auf die Stelle wurde ich gestern auch angesprochen. Ich habe da jetzt eine Art Exkurs draus gemacht.
forumnewbie hat geschrieben:
Aus dem Datentyp (char **) wird durch den Dereferenzierungsoperator der „*“ weggenommen: man erhält den Datentyp (char *). Aus dem Datentyp (char *) wird der Datentyp (char).
Warum fällt jedes mal ein * weg und wofür macht man das überhaupt? Welchen praktischen Nutzen hat es ** zu benutzen?
Also warum soll man so etwas machen char ** pointerPointer = &pointer; ? Habe das leider nicht verstanden. Vielleicht könnte man das irgendwie anschaulich/grafisch erklären.
Ich habe einiges hier erweitert und eine Übungsaufgabe eingefügt. Schau doch mal, ob das nachvollziehbarer ist.
forumnewbie hat geschrieben:Lob: Verwandtschaft von Arrays und Zeigern - gutes Beispiel! Zwar am Anfang nicht leicht zu verstehen, aber man sieht wie man über die Adresse des Zeigers auf ein Array-Element mittels eines Zeigeroperators zugreifen kann.

array[index] entspricht *(zeiger+index)
&array[index] entspricht zeiger+index
Richtig? Gibt es auch *array[index]? Wäre das vielleicht **(zeiger+index)?
Die ersten beiden sind grundsätzlich richtig, der dritte Fall funktioniert nur dann, wenn es sich um ein Array aus Zeigern handelt.
Nach dem Dereferenzieren, was entweder mit array[index] oder mit dem Dereferenzierungsoperator passiert, verliert der Datentyp ja ein '*'. Ein (char **) könnte man allerdings entsprechend 2x dereferenzieren, da nach dem 1. Dereferenzieren ja ein (char *) überbleibt.
forumnewbie hat geschrieben:
Wo ist dann der Unterschied? Ein Array mit angegebener Größe stellt Speicher zur Verfügung - ein Pointer nicht.
char * pointer; // Kein eigener Speicher, zeigt irgendwo hin
Ein (leerer) Zeiger müsste aber doch auch irgendwo im Arbeitsspeicher sein, oder nicht? Wenn ich &Zeiger verwende, dann erhalte ich seine persönliche Speicheradresse, oder verstehe ich das falsch?
Das verstehst Du vollkommen richtig. Ich habe den Text geändert:
Wo ist dann der Unterschied? Ein Array mit angegebener Größe stellt den gewünschten Speicher zur Verfügung - ein Pointer hingegen stellt nur soviel Speicher zur Verfügung, wie eine Adresse benötigt.
Ein Array mit angegebener Größe stellt den gewünschten Speicher zur Verfügung - ein Pointer hingegen stellt nur soviel Speicher zur Verfügung, wie eine Adresse benötigt. Wohin der Pointer auch immer zeigt: Dort findet sich erstmal kein Speicher, den wir benutzen dürfen.
forumnewbie hat geschrieben:
Konstante Strings
Nochmal zum Geschwindigkeitsunterschied zwischen char text[] = "proggen.org"; und char const * text = "proggen.org";
Bei der ersten Variante muss zuerst ein Array aus n Elementen angelegt werden und in jedes Array-Element wird ein Zeichen reinkopiert und anschließend im Arbeitsspeicher komplett abgelegt, nachdem das Array erstmal alle seine "Spalten" gefüllt hat?
Und bei der zweiten wird nur die Anfangsadresse an den Zeiger zugewiesen und anschließend sofort das Array/Text in dem Arbeitsspeicher abgelegt. Somit spart man sich n-1 Kopiervorgänge. Verstehe ich das richtig?
Wenn ja, dann würde ich das in der Beschreibung so ausführlicher erklären, wenn nein, anders erklären - dann habe ich es nicht richtig verstanden :)
Dafür hast Du es aber richtig wiedergegeben.
Ich habe das Unterkapitel etwas vergrößert und werde es wohl auf kurz oder lang zu einem eigenen Kapitel machen.
forumnewbie hat geschrieben:
Sie eignen sich also dazu, um bei der Initialisierung eines Arrays in das Array kopiert zu werden, so dass wir dann unser Array verändern können, ...
Habe diesen Satz erst nach mehreren Versuchen verstanden, was hier gemeint ist. Eventuell bisschen einfacher formulieren.
Ich hab's versucht. Gelungen?
forumnewbie hat geschrieben:
Wir haben uns vorhin die Adresse wie einen Index in einem Array vorgestellt. Und das trifft es sehr gut, denn ein Array ist für viele Entwickler einfacher zu verstehen, als ein Pointer, doch in Wirklichkeit ist ein Array komplizierter als ein Zeiger.
Für wenn ist ein Array komplizierter und warum? Arrays/Vektoren kenne ich aus der Mathematik, und mit Zeigern habe ich immer noch Schwierigkeiten. Für mich sind Zeiger viel abstrakter und somit komplizierter.
Ich habe die Einleitung "Was ist ein Zeiger" dafür mal überarbeitet.
forumnewbie hat geschrieben:Bei diesem Zeiger-Tutorial habe ich an einigen Stellen Verständnisprobleme. Es wäre super, wenn jemand mir diese Fragen - zumindest zum Zeiger-Tutorial beantworten könnte. Und dann ggf. die Erklärungen im Toturial verbessern/anpassen.
Ich beantworte Dir gerne alle Fragen, aber für so viele brauche ich ein paar ruhige Stunden. Entschuldige, dass es so lange dauert, aber auch hier sind Deine Fragen verwertet worden:

Unterschiede durch Dein Posting: http://www.proggen.org/doku.php?id=c:tu ... sidebyside
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten