char-array mit pointer durchlaufen


  • Mod

    zeigerle schrieb:

    Es ist schon richtig, das keyboard_array ein Pointer ist
    nein, nein und nochmals nein.

    doch, doch und nochmals doch.

    die daten liegen auf dem stack und ein array ist nur ein konstanter zeiger darauf

    char daten1[8];
    char const *daten2 = daten1;
    

    beide sind intern identisch

    für den compiler sind sie vllt. verschieden aber auf assemblerebene ist das gleich

    Was soll das denn sein: intern, assemblerebene? Und was hat das mit dem Problem zu tun?
    keyboard_input ist kein Zeiger, sowenig wie es daten1 ist. Der ++ Operator benötigt als Argument ein modifizierbares skalares lvalue. keyboard_input ist zwar modifizierbar und ein lvalue, aber kein Skalar und kann auch nicht implizit in ein solches umgewandelt werden.

    xxyyzz schrieb:

    camper schrieb:

    Schau dir Zeile 19 an, dann Zeile 4, und dann erkläre bitte, was Zeile 19 bewirken soll.

    camper schrieb:

    squis schrieb:

    keyboard_input zeigt dabei auf das erste element von keyboard_input.

    Und bei diesem Satz wirst du nicht stutzig?

    camper schrieb:

    Fledi schrieb:

    Es ist schon richtig, das keyboard_array ein Pointer ist

    nein, nein und nochmals nein.

    Diese Hinweise helfen nicht!

    Das könnte stimmen, oder auch nicht. Jedenfalls ist es allemal besser als immer wieder den gleichen Unfug (Array=Zeiger) zu verbreiten. Das wird durch Wiederholung auch nicht richtiger.


  • Administrator

    Wieso gibt es eigentlich diese Unterscheidung? Das ist mir irgendwie bis heute noch nicht so ganz klar.

    Ich persönlich finde irgendwie, dass dies nur die Verwendung der Arrays verkompliziert. Ok, vielleicht in C++ klug, damit die Leute den std::vector verwenden, aber das wird wohl kaum der Grund sein 🙂

    Grüssli


  • Mod

    Dravere schrieb:

    Wieso gibt es eigentlich diese Unterscheidung?

    Weil es sich um völlig verschiedene Dinge handelt, und wir Dinge dann nicht gleich bezeichnen, wenn es auf diese Unterschiede ankommt.
    Umgekehrt ist mir nicht klar, wie man auf die Idee kommen kann, dass es sich um das Gleiche handelte.
    Sicherlich wirst du anerkennen, das es einen Unterschied gibt zwischen deiner Wohnung und der Adresse dieser Wohnung. Natürlich gibt es zwischen beiden einen Zusammenhang und es kann auch vorkommen, dass man an Stelle des einen das andere verwenden kann, z.B. könntest du auf die Frage, wo du wohnst, mit der Angabe der Adresse antworten oder aber, wenn sie denn in Sichtweite ist, einfach darauf zeigen.
    Ein Array ist ein Objekt, das aus einzelnen gleichartigen Subobjekten besteht. Objekte sind zusammenhängende Speicherbereiche. Jedem solchen Speicherbereich ist eine (Anfangs-)adresse zugeordnet. Ein Zeigerwert stellt eine typisierte (indem der Typ des Objektes an dieser Stelle Teil des Zeigertyps ist) Adressinformation dar.
    Zeigerobjekte sind Objekte, die diese Adressinformation speichern können.
    Diese beiden Dinge (Array, Zeiger) zusammenzuwerfen ergibt hinten und vorne keine Sinn.



  • Zeigerobjekte sind Objekte, die diese Adressinformation speichern können.

    Der Feldname speichert die Adresse des ersten Feldelementes. Wieso ist er da kein Zeiger??


  • Administrator

    camper schrieb:

    Diese beiden Dinge (Array, Zeiger) zusammenzuwerfen ergibt hinten und vorne keine Sinn.

    Ich weiss, dass es zwei grundsätzlich völlig unterschiedliche Dinge sind. Grundsätzlich haben sie nichts miteinander zu tun, da geb ich dir definitiv auch recht. Aber das ist die Theorie. In der Praxis wäre es äusserst angenehm, wenn diese Unterscheidung nicht stattfinden würde. Oder empfindest du es als praktisch, solche Dinge zu machen?

    &array[0];
    

    Wenn noch der Fall wäre, wie in Java, dass das Array ein Length Attribute hätte, dann wäre für mich die Unterscheidung auch in der Praxis verständlich. Aber tatsächlich hast du ein Array, welches sich fast 1:1 wie ein Zeiger verhält und trotzdem keiner ist.

    Ich sehe in der Praxis einfach den Vorteil dieser Unterscheidung nicht. Vielleicht arbeite ich aber auch zu wenig mit C-Arrays, um den Vorteil zu sehen.

    Grüssli


  • Mod

    Fledi schrieb:

    Zeigerobjekte sind Objekte, die diese Adressinformation speichern können.

    Der Feldname speichert die Adresse des ersten Feldelementes. Wieso ist er da kein Zeiger??

    Weil du "speichern" in einem völlig anderen Sinn gebrauchst.
    Zwar gehört zum Arrayobjekt eine Adresse, aber diese Adressinformation existiert nicht selbst im Speicher und ist daher auch nicht adressierbar.

    Man könnte genauso gut fragen, wieso

    5++
    

    nicht funktioniert.



  • freut mich das meine einfache frage ( ich dachte zumindest sie sei einfach ) so eine angeregt diskussion gefördert hat :-).

    mir wurde das im studium so vermittelt (oder ich habs so verstanden) das ein variable die ein char array ist

    char mein_array[5];
    

    ein Zeiger auf die speicheradresse von mein_array[0] ist. Den Fehler den ich gemacht hab kam dadurch zu stände das ich bisher immer nur in funktionen bzw. methoden mit den arrays über pointer gearbeitet hab, weswegen ich nie in ds loch mit dem 'konstanten' Zeiger gefallen bin.

    eig. muss das auch ein zeiger sein, sons würde sowas doch gar nicht funktionieren:

    void copy(char * a, char * b);
    
    int main(int argc, char **argv)
    {
       char in[6] = {'H','a','l','l','o','\0'};
       char out[6];
       copy(in, out);
       return 0;
    }
    
    void copy (char * a, char * b)
    {
       while(*b++ = *a++);
    }
    

    Die Funktion erwartet eine pointer, wäre das array kein pointer würd das schon beim kompilieren gegen di wand rennen oder nicht ?


  • Administrator

    @squis,

    char array1[] = "Hallo";
    // Dann ist array1, ca. gleichwertig zu:
    char* const array2 = "Hallo";
    

    Und einen konstanten Zeiger darf man auch kopieren, solange der Zeiger selbst nicht verändert wird.
    Aber eben, grundsätzlich muss man es differenzieren, das eine ist ein Array und das andere ein konstanter Zeiger. Es macht in meinen Augen nicht all zu viel Sinn, aber was solls.

    Grüssli



  • Dravere schrieb:

    @squis,

    char array1[] = "Hallo";
    // Dann ist array1, ca. gleichwertig zu:
    char* const array2 = "Hallo";
    

    Und einen konstanten Zeiger darf man auch kopieren, solange der Zeiger selbst nicht verändert wird.
    Aber eben, grundsätzlich muss man es differenzieren, das eine ist ein Array und das andere ein konstanter Zeiger. Es macht in meinen Augen nicht all zu viel Sinn, aber was solls.

    Grüssli

    Die Gemeinsamkeiten von Zeigern und Adressen versteht ihr, aber macht Euch den Unterschied zwischen Zeiger und Adressen klar!
    Zeiger sind lvalues - Adressen sind rvalues!
    Mit dem Adressoperator kann man Zeigern Adressen von Variablen zuweisen oder Adressen repraesentieren
    - Ausnahme bilden Arrays, der Arrayname seht für die Adresse des ersten Arrayelements (&array[0]).

    #include <iostream>
    
    using namespace std;
    
    int main() {
    
    	char array1[] = "Hallo";
        // array1 (= null-terminierte Zeichenkette) liegt auf dem Stack!
    
    	if (array1 == *&array1 && array1 == &array1[0])
    		cout << "array1 repraesentiert die Adresse von array1[0]( &array1[0] bzw. *&array1 !)" << endl;
    
    	char* const array2 = "Hallo";    
    	// array2 (Zeiger auf konstante null-terminierte Zeichenkette). Die liegt im schreibgeschuetzten Bereich! 
    
    	array1[0]  = 'B';   // ok! 
    
    	cout << array1 << endl;
    
    	array2[0] = 'B';   // Fehler, weil Zugriffsverletzung beim Schreiben! 
    
    	return 0;
    }
    

    mfg


  • Administrator

    @egon2,
    Der Unterschied ist mir klar! Das "Hallo" war vielleicht etwas schlecht gewählt. Die Zugriffsverletzung kommt nur daher, weil "Hallo" ein literal ist. Man hätte es auch so machen können:

    char array1[5];
    // Dann ist array1, ca. gleichwertig zu:
    char* const array2 = new char[5];
    

    Nur das halt der Speicherort ein anderer ist, ok dann eben halt so:

    char array1[];
    // Dann ist array1, ca. gleichwertig zu:
    char* const array2;
    

    Mir ging es eigentlich nur um den Typ, welcher array1 hat. Und es wäre deutlich praktischer, wenn der Typ von array1 eher ein char* wäre, als ein char* const . Das würde das Handhaben von Arrays vereinfachen, zumindest in meinen Augen.

    Grüssli


  • Mod

    Dravere schrieb:

    @egon2,
    Der Unterschied ist mir klar!

    Könntest du es auch in Worte fassen?

    Dravere schrieb:

    Grundsätzlich haben sie nichts miteinander zu tun, da geb ich dir definitiv auch recht. Aber das ist die Theorie. In der Praxis wäre es äusserst angenehm, wenn diese Unterscheidung nicht stattfinden würde. Oder empfindest du es als praktisch, solche Dinge zu machen?

    &array[0];
    

    Ich verstehe nicht, was du hiermit ausdrücken möchtest. Worin besteht denn nun der Unterschied zwischen "Theorie" und deiner "Praxis"?

    egon schrieb:

    Die Gemeinsamkeiten von Zeigern und Adressen versteht ihr, aber macht Euch den Unterschied zwischen Zeiger und Adressen klar!
    Zeiger sind lvalues - Adressen sind rvalues!

    Ich bezweifle, dass das bloße Einbringen neuer Begriffe in die Diskussion geeignet, diese weiterzuführen. Wenn du nicht gleichzeitig eine brauchbare Definition für L- und R-values lieferst, ist dieser Satz ohne Gehalt.

    Ich habe ohnehin das Gefühl, dass hier noch grundlegendere Verständnisprobleme bestehen, hinsichtlich dessen, was Speicher ist, und was "gespeichert" wird.

    Betrachten wir einfach mal

    int x = 42;
    int y[10] = { 42 };
    int* p;
    bool b;
    p = &42;              // (1)
    p = &x;               // (2)
    p = y;                // (3)
    p = &y;               // (4)
    p = &y[0];            // (5)
    b = 42;               // (6)
    b = &x;               // (7)
    b = y;                // (8)
    b = &y;               // (9)
    b = &y[0];            // (10)
    

    Nur die Ausdrücke (1) und (4) sind hierbei fehlerhaft.

    squis schrieb:

    Die Funktion erwartet eine pointer, wäre das array kein pointer würd das schon beim kompilieren gegen di wand rennen oder nicht ?

    oder nicht.
    Falls dieses Argument gültig wäre, müsste man entsprechend (8) auch sagen können, dass ein Array ein bool ist, ebenso wie ein Zeiger ein bool wäre. Das können wir beliebig weitertreiben:

    void f();
    b = f;
    b = 42.424242;
    struct Foo { void bar() {} int x_; };
    b = &Foo::bar;
    b = &Foo::x_;
    

    also sind auch Funktionen, double, Zeiger auf Member alle bool?
    Wozu machen wir uns dann eigentlich die Mühe, Typen einzuführen, wenn am Ende doch alles bool ist?
    Offensichtlich steht das Argument eben nicht. Und zwar deshalb, weil es von einer falschen Voraussetzung ausgeht, auf die ich bereits mehrfach hingewiesen habe. Mir fällt schlicht nichts mehr ein, um es deutlicher zu machen.
    Diese Voraussetzung, die falsch ist, lautet: Ein X, das dort verwendet werden kann, wo ein Y erwartet wird, ist selbst ein Y.
    Richtig wäre: Ein X kann dort verwendet werden, wo ein Y erwartet wird, wenn X implizit in Y konvertiert werden kann.
    Im Umkehrschluss folgt daraus, dass offensichtlich ein Array-Ausdruck in einen Zeigerausdruck umgewandelt werden kann, weil wir eben wissen, dass wir regelmäßig an Stelle eines Zeigerarguments auch ein Array einsetzen dürfen, was nicht bestritten wurde.
    X und Y wären nur dann gleich, wenn diese Konvertierung in beide Richtungen und in allen Fällen möglich wäre. Das ist im Verhältnis zwischen Arrays und Zeigern offensichtlich nicht so. Also sind sie nicht gleich. q.e.d. Kein aber. Hier kommt nichts mehr von wegen Theorie und Praxis - was im Übrigen nichts weiter als ein Phrase ohne Gehalt ist.

    Betrachten wir

    1 = 2;
    

    Das ist kein zulässiger Ausdruck. Warum? Weil 1 eine Konstante (wir nennen so etwas Literal) ist, und somit nicht geändert werden kann? Das kann man sicherlich so sagen; es kann zu Missverständnissen führen, weil wir im Grunde zwei Arten von Konstanz kennen.

    const int x = 1;
    x = 2;
    

    Auch das ist nicht erlaubt. Und auch hier ist x konstant. Aber es eine andere Art von Konstanz. "1" stellt den Wert 1 an sich dar - es ist schlicht sinnlos, diesen modifizieren zu wollen. Im Falle von x ist das anders: Hier ist x nur deshalb konstant, weil es ausdrücklich so definiert haben. Wir könnten uns das const wegdenken, dann ergibt x=2; plötzlich Sinn. Das funktioniert nicht bei 1=2

    Das Ganze lässt sich auch technisch begründen, und sich diese Begründung zu eigen zu machen hilft, Fehlermeldungen des Compilers zu verstehen. Betrachten wir

    p = &42;
    

    Das ist nicht möglich, denn der Adressoperator liefert uns die Adresse eines Speicherbereichs. 42 aber stellt von vornherein keinen Speicher dar! (es ist kein Objekt) Betrachten wir das aus diesem Blickwinkel, wird die Begründung bzgl. 1=2 einfacher: Bei einer Zuweisung ändern wir den Zustand von Speicher, nämlich dem Speicher, der durch den linken Operanden bestimmt wird. 1 bestimmt aber keinen Speicherort und ist folglich kein zulässiger linker Operand des Zuweisungsoperators. Umgekehrt darf 1 sehr wohl auf der rechten Seite der Zuweisung stehen, denn der rechte Operator bestimmt ja den zuzuweisenden Wert. Schreiben wird aber zum Beispiel

    int x = 1, y = 2;
    x = y;
    

    dann steht auch auf der rechten Seite kein Wert, sondern ein Ausdruck, der zunächst einmal nur das Objekt (=den Speicherbereich) y bezeichnet. Die Zuweisung ist trotzdem möglich, weil es eine implizite Konvertierung gibt, die einen skalaren Ausdruck, der ein Objekt bezeichnet, in einen Ausdruck umwandelt, der den Wert des Objektes repräsentiert. Diese Konvertierung selbst steht - im Allgemeinen - für einen tatsächlich stattfinden Vorgang: das "Lesen" des Wertes eines Objektes.
    Um die Diskussion zu vereinfachen, geben wir den verschiedenen Ausdrücken einen Namen: ein Ausdruck, der auf ein Objekt verweist, heißt lvalue, ein Ausdruck, der einen möglichen Wert eines Objektes beschreibt, heißt rvalue.
    Auf der linken Seite einer Zuweisung muss ein lvalue stehen. Offensichtlich genügt das nicht, wie wir am Beispiel

    const int x = 1;
    x = 2;
    

    gesehen haben. Manche lvalues sind nämlich wegen const-Qualifikation nicht modifizierbar. Wir sagen daher, dass der linke Operand der Zuweisung ein modifizierbarer lvalue sein muss. Andere Operatoren haben andere Voraussetzungen:
    Der Adressoperator begnügt sich mit jeder Art lvalue, die meisten Operatoren begnügen sich dagegen mit rvalues, es für das Ergebnis der Addition schlicht egal, ob der Operand ein Literal war, durch Lesen des Wertes einer Variablen bestimmt wurde oder selbst das Ergebnis einer anderen Operation ist. Immer dort, wo ein rvalue erwartet wird, darf statt dessen ein lvalue eingesetzt werden, wenn dieses implizit in das jeweilige rvalue konvertiert werden kann. Umgekehrt gibt es keine Konvertierung von r- in lvalues (denn es ergibt keinen Sinn: da lvalues auf Speicher verweisen, muss dieser Speicher ja irgendwoher bestimmt sein; und diese Bestimmung liegt nicht im rvalue, andernfalls wäre es ja bereits ein lvalue).
    Bis zu diesem Zeitpunkt haben ich ausschließlich skalare Ausdrücke behandelt.
    Tatsächlich ist es so, dass in C++ jeder Ausdruck entweder ein l- oder ein rvalue ist. Dies wird möglich, indem die Definition von l- und rvalue geschickt auf andere Ausdrücke erweitert wird; solchen die nicht skalar sind, oder nicht einmal einen Objekttyp haben.
    Arrays sind ein solcher Fall. Während wir kein Problem haben, zu definieren, was ein Array-lvalue sein soll, nämlich ein Ausdruck, der auf ein Array verweist

    int foo[10];
    foo; // Array-lvalue
    

    stellen wir fest, dass dies nicht so ohne weiteres für rvalues möglich ist. Tatsächlich ist es sogar so, das Array-rvalues ebenfalls auf Arrays (also Objekte) verweisen (diese Eigenschaft teilen Arrays mit Klassen); es handelt sich allerdings dabei um recht exotische Gebilde. Umgekehrt hat C++ keinen für Begriff für den Wert eines Arrays, also gewissermaßen die Gesamtheit aller Einzelwerte eines Arrays, es ist daher auch nicht möglich, in einem Ausdruck irgendwie auf diese Gesamtheit zu verweisen. Das bedeutet dann unter anderem, dass es keinen Operator gibt, der auf alle Werte eines Arrays mit einem Mal zugreifen könnte - das ist auch die Ursache, warum man Arrays nicht zuweisen kann, und weshalb sie nicht als Argumente oder Rückgabewerte von Funktionen auftreten können.
    Da es nun - im Gegensatz zu skalaren Ausdrücken - keine Möglichkeit gibt, aus einer Arraybestimmung einen Arrayswert "zu lesen" (weil wir keinen Begriff des Arraywertes haben), existiert konsequenterweise auch keine implizite Konvertierung von Array-lvalues in Array-rvalues. Nun wollen wir aber mit Arrays arbeiten, das bedeutet primär die Anwendung des Indexoperators []. Nach all dem was gesagt wurde, müsste ein solche Operator je ein Array-lvalue und einen integralen Ausruck als Argumente haben. Gehen wir - wie es historisch war - davon aus, dass bereits Zeigerarithmetik und der Indexoperator für Zeiger existieren, stellen wir fest, dass wir diesen zu definierenden Array-Indexoperator einfach auf Zeiger zurückführen können; es ist

    int foo[10];
    foo[ i ]    // unser zu definierender Operator
    = *( (int*)&foo + i)
    

    (wir könnten auch sagen, dass das Layout von Arrays explizit so festgelegt wurde, dass diese Identität gewährleistet wird). Aus Sicht des C-Spracherfinders haben wir jetzt also die Möglichkeit von zwei Indexoperatoren:
    einer, der Zeiger-rvalues und integrale rvalues kombiniert, und einen, der Array-lvalues und integrale rvalues kombiniert. Dieser Weg wäre gangbar gewesen (und hätte vermutlich zu weniger Konfusion geführt); dies ist allerdings nicht der Weg, der für C gewählt wurde. Anstatt dem Indexoperator eine Doppelbedeutung zu geben, wurde statt dessen eine implizite Konvertierung von Array-lvalues in Zeiger-rvalues definiert, der Semantik obigem Cast-Ausdruck entspricht:

    T foo[..]
    T* p = foo; // entspricht
    T* p = (T*)&foo;
    

    Diese Definition ist überhaupt erst möglich, ohne Mehrdeutigkeiten zu produzieren, weil eben die gewöhnliche l- zu rvalue-Konvertierung für Arrays nicht existiert. Das Ganze hat Auswirkungen, die zu Konfusion führen, denn diese implizite Konvertierung findet immer dann statt, wenn ein Array in einem Kontext verwendet wird, der ein rvalue benötigt, und das ist der weitaus größte Teil. Es ist tatsächlich einfacher, zu bestimmen, wann diese Konvertierung nicht stattfindet: dann, wenn der jeweilige Kontext, der auf den Arrayausdruck angewandt wird, für Array eine eigene Bedeutung hat, das sind:
    & (Adressoperator)
    sizeof
    Binden an eine Referenz
    Bedeutet das, dass Arrays Zeiger sind? Falls du immer noch dieser Ansicht bist, muss es offenbar jemand anderes erklären.

    Bezüglich des Verhältnisses von Adressen und Zeigern, erinnert mich das an eine schon mal geführte sinnlose Diskussion, ob Adressen einen (Zeiger-)Typ haben oder nicht. Dabei ist leicht einsichtig, dass wir einen untypisierten Adressbegriff neben einem typisierten Zeigerwert haben können.
    Betrachten wir

    42 == 42u
    

    sind die beiden Operanden gleich? Ja, denn beide repräsentieren die natürliche Zahl 42. Beide Ausdrücke sind aber nicht identisch, denn dieser gleiche Wert wird durch verschiedene Typen (int, unsigned) dargestellt. Nicht anders verhält es sich mit Zeigern und Adressen. Während die Adresse nur die abstrakte Vorstellung eines Speicherortes darstellt - und also solche keinen Typ hat - ist ein konkreter Zeigerwert (rvalue) dann eben die Darstellung dieser Adresse, unter Benutzung eines bestimmten Zeigertyps. Zeigerobjekte wiederum speichern folglich Zeigerwerte. Es ist informell unproblematisch, zu sagen, dass Zeiger Adressen speichern - schon weil der Begriff Adresse nicht genau definiert wird - denn im Allgemeinen er gibt sich der Sinn der Aussage aus dem Kontext, in dem sie gemacht wird. Ähnlich wie häufig gesagt wird, ein Objekt wäre ein lvalue, oder eine Konstante ein rvalue, obwohl es streng genommen die Ausdrücke sind, die auf diese Objekte oder Konstanten verweisen bzw. diese repräsentieren, welche l- bzw. rvalues sind. Andere Begriffe - z.B. der des "temporären Objektes" (was bitteschön macht ein Objekt temporär?) - werden nur verständlich, wenn man sich einmal um etwas exaktere Klärung von Begriffen bemüht.


  • Administrator

    Guter Artikel camper, sollte man eigentlich irgendwie abspeichern! Gebracht hat es mir allerdings nichts 🙂
    Jetzt muss ich mir überlegen, wie ich dir das am besten erkläre. Allerdings probiere ich mich etwas kürzer zu fassen.

    Ok, vielleicht zuerst einmal die Art, wie ich den Typ des aktuellen Arrays sehe, ausgedrückt in C++ Syntax:

    class Array // Ja, eine Klasse! Kein Zeiger-Objekt!
    {
      /* ... */
    public:
      operator char*(); // Implizit konvertierbar zu einem Zeiger!
    
      operator [](int); // Mit Indexoperator.
    
      /* .. usw. .. */
    }
    

    Meine Frage an sich ist gewesen, wäre es nicht vernünftiger gewesen, bei der "Erfindung" von Arrays in C++, die "Klasse" Array gleich komplett fallen zu lassen? Also dass es kein Array-Konzept gibt und somit folgendes gelten würde:

    char array[10]; // array ist ein char*
    

    Ich muss allerdings zugeben, dass dies dann nicht wirklich gut durchgezogen wäre und eigentlich einen leichten Bruch in der C++ Idee wäre. Deshalb habe ich auch vom Unterschied zwischen Theorie und Praxis geredet. So wie es jetzt ist, ist es streng nach Theorie, bzw. nach der C++ Idee, fortgeführt. Und in mir hat sich halt die Frage gestellt, ob es in der Praxis nicht vernünftiger gewesen wäre, dies als Zeiger zu sehen.
    Man hätte natürlich auch dem Array-Konzept einen ++, bzw. einen --, Operator geben können. Was allerdings sicherlich auch nicht so ganz der grundsätzlichen Idee entsprechen würde. Schliesslich hat man bei einem std::vector auch kein ++ oder -- und würde es wohl auch als ziemlich unsinng ansehen.

    Ich frage mich halt, obwohl es einen gewissen Bruch darstellen würde, wäre es in der Praxis nicht angenehmer gewesen? Ich selber kann das zu wenig beurteilen, da ich zu wenig C-Arrays benutze. Ich habe mich einfach nur diese Frage gestellt 😉

    Grüssli


  • Mod

    @Dravere: Mir wir jetzt einigermaßen klar, worauf du hinaus willst. Wenn ich es richtig verstehe, geht es dir um die Frage, ob ein anderer Sprachentwurf, der Arrays auf anderer Weise behandelt, möglicherweise zu besserem Code führen würde. Bisher habe ich deine Beiträge eher dahingehend aufgefasst, dass du mir wenigstens tendenziell widersprechen möchtest - meine Antworten waren daher auch nicht als "Hilfe" für dich anzusehen. Jedenfalls bezweifle ich, dass diese Fragestellung überhaupt etwas mit dem Problem des OP zu tun hat; denn unabhängig von der Antwort auf dein Problem kann die Frage des OP natürlich nur anhand der tatsächlich gegebenen Sprache beantwortet werden.
    Es wäre angenehm, wenn du von solchem Mißbrauch von Wörtern wie "Theorie" und "Praxis" absehen würdest - sie sind hier prinzipiell deplaziert, und haben bei diesem Gebrauch auch einen abwertenden Charakter.
    Falls du dein Problem zur Diskussion stellen möchtest, solltest du dafür einen neuen Thread erstellen. Natürlich ist es letztlich deine Aufgabe, einen hinreichend vollständigen Gegenentwurf zu entwickeln, den man dann mit der existierenden Sprache vergleichen könnte. Ins Blaue hinein zu fragen, ob man etwas besser machen könnte, ist nicht verkehrt aber einfach unzureichend, um darauf basierend eine Diskussion zu führen.


  • Administrator

    Naja, in etwa, ja. Grundsätzlich oder besser ursprünglich ging es mir darum zu vestehen, wieso man sich so entschieden hat, beim Sprachentwurf von Arrays. Ging es dabei wirklich nur darum, dass man der Idee von C oder C++ treu bleibt oder hat man sich noch anderes dabei überlegt?
    Also gibt es mit dem aktuellen Entwurf von Arrays vielleicht irgendwelche Vorteile? Ich persönlich sehe hauptsächlich Nachteile beim Arbeiten mit Arrays und der OP hat sich ja quasi auch etwas genervt, dass er den operator ++ nicht anwenden konnte. Nach dem nun zu genüge erklärt wurde, wieso das nicht geht, wäre es irgendwie noch sinnvoll, wenn man die Vorteile dieser Unterscheidung auflisten würde.

    Also in etwa:
    Ein Array ist kein Zeiger, sondern nur implizit in einen Zeiger umwandelbar. Dies hat den Vorteil ...

    Derzeit steht in diesem Thread eigentlich nur:
    Es ist, weil es so ist!

    Grüssli



  • Wie heißt es immer so schön: Es ist gewachsen.
    Oder: Das ist historisch bedingt.

    😃



  • Fellhuhn schrieb:

    Wie heißt es immer so schön: Es ist gewachsen.
    Oder: Das ist historisch bedingt.

    Ich kannte es eigentlich immer nur in Kombination, die gerne in Vorstellungsgesprächen verwendt wird ("...Es handelt sich um eine historisch gewachsene Anwendung...") und bei mir sofort die Alarmglocken schrillen lässt (häufig impliziert das auch das Codepflege/Refactoring unerwünscht ist, und nur als Zeitverschwendung angesehen wird).

    cu André


Anmelden zum Antworten