Array, Zuweisungsfehler



  • Oh tut mir leid, die Frage gehört natürlich in die C++ Sektion...

    Wo liegt denn der unterschied zwischen std::array und den Arrays, die ich verwende?

    Ich habe es so gelert, dass, wenn man ein Array definiert, also "int a[size]", "a" einen Pointer auf das erste Element darstellt. Also solte man doch die Zuweisung "a=pointer" machen können?

    Umgekehrt, kann man ja ein "Array" ja auch so erstellen:

    int* a;
    
    a[0] = 3;
    a[1] =...
    .
    .
    .
    

    Der Unterschied dabei liegt dabei, wie ich meine nur bei der Speicherallokation. Bei der ersten Variante wird Speicher in der Grössenordnung sze reserviert. Bei der 2ten werden einfach unkontrolliert die auf die Anfangsadressen folgenden Sektionen beschrieben. Stimmt das so?



  • kaenzign schrieb:

    Wo liegt denn der unterschied zwischen std::array und den Arrays, die ich verwende?

    Rohe Arrays sind in ihrem Verhalten manchmal etwas...eigen. std::array ist im Prinzip nichts anderes als ein struct, das ein Array enthält. Dadurch verhält sich das ganze dann wie von dir erwartet, beispielsweise kannst du ein std::array by value an Funktionen übergeben und aus einer Funktion returnen, was mit rohen Arrays gar nicht möglich ist...

    kaenzign schrieb:

    Ich habe es so gelert, dass, wenn man ein Array definiert, also "int a[size]", "a" einen Pointer auf das erste Element darstellt. Also solte man doch die Zuweisung "a=pointer" machen können?

    Das ist nicht korrekt, a ist ein Array und kein Pointer auf das erste Element. Einfacher Beweis: sizeof(a) wird einen anderen Wert liefern als sizeof(pointer). a kann lediglich implizit in einen Pointer auf das erste Element umgewandelt werden, so wie z.B. ein int auch implizit in einen float umgewandelt werden kann.

    kaenzign schrieb:

    Umgekehrt, kann man ja ein "Array" ja auch so erstellen:

    int* a;
    
    a[0] = 3;
    a[1] =...
    .
    .
    .
    

    Nope, da wird nirgendwo ein Array oder irgendetwas, das einem Array ähnlich wäre, erstellt, sondern versucht, einfach irgendwo in den Speicher zu schreiben. Im besten Fall erwischt dich das Betriebssytstem und beendet dein Programm mit einem schwerwiegenden Fehler, aber wenn du Pech hast, funktioniert es einfach, zerstört irgendwelche Strukturen im Speicher und führt so zu unglaublich schwer zu findenden weil völlig undurchschaubaren Bugs...

    kaenzign schrieb:

    Der Unterschied dabei liegt dabei, wie ich meine nur bei der Speicherallokation. Bei der ersten Variante wird Speicher in der Grössenordnung sze reserviert. Bei der 2ten werden einfach unkontrolliert die auf die Anfangsadressen folgenden Sektionen beschrieben. Stimmt das so?

    Ja, das ist, was am Ende passieren wird. Einfach unkontrolliert irgendwo in den Speicher schreiben ist aber keine erlaubte Vorgehensweise, sondern ein Bug, der so gefährlich ist, dass es sogar einen eigenen Namen dafür gibt...



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ (auch C++0x und C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • kaenzign schrieb:

    Ich habe es so gelert, dass, wenn man ein Array definiert, also "int a[size]", "a" einen Pointer auf das erste Element darstellt. Also solte man doch die Zuweisung "a=pointer" machen können?

    Das ist nicht korrekt, a ist ein Array und kein Pointer auf das erste Element. Einfacher Beweis: sizeof(a) wird einen anderen Wert liefern als sizeof(pointer). a kann lediglich implizit in einen Pointer auf das erste Element umgewandelt werden, so wie z.B. ein int auch implizit in einen float umgewandelt werden kann.

    Warum meckert der Compiler dann bei

    int* foo(int x[])
    {
        for(int i=0; i<sizeof(x); i++)
        {
            x[i] = i;
        }
    
        return x;
    }
    

    nicht?

    Die Funktion erwartet ja einen Pointer auf int als Rückgabewert, ich gebe aber letzendlich ein Array, oder eben wie ich zu glauben meinte, einen Pointer auf das erste Element des Arrays. (Was dein Argment mit dem sizeof, aber eindeutig widerlegt..)

    Wie könnte ich denn hier z.B das x in einen Pointer umwandeln?
    Einfach so: (int*)x ?
    Der compiler schluckts auf jeden Fall...

    Wenn ich dann aber weiter unten die Zuweisung wie dementsprechend ändere:
    (int*)a = foo(a); läuft es wieder nicht...


  • Mod

    void foo(int x[]);
    

    ist exakt identisch zu

    void foo(int *x);
    

    . Bloß unterschiedliche Schreibweisen. Bei beiden ist x ein Zeiger.

    P.S.: Achtung! Folgendes ist nicht identisch:

    char foo[] = "Abc";
    char *foo  = "Abc";
    

    Weiterhin ist "der Compiler schluckt es" kein Kriterium, an dem man sich orientieren sollte. Allerlei Unsinn ist grammatikalisch richtig, und nur das interessiert den Compiler. Gerade mit den C-Casts (die einem reinterpret_cast in C++ entsprechen können) kann man den Compiler dazu bringen, auch beim gröbsten Unfug die Klappe zu halten.



  • Wenn du ein Array, egal was für eins, an eine Funktion übergibst, dann zerfällt das Array immer automatisch in einen Zeiger auf das erste Element des Arrays (array-to-pointer-decay). Daran kannst du auch nichts ändern, C++ will das so.



  • Danke für die schnellen Antworte, jetzt wird mir das ganze langsam klarer.

    Hier noch ein kurzes Beispiel zur selben Thematik:

    int a [8] = {2,4,6,8,10,12,14,16};
        *a = a[6];
        a[6] = (int)a;
    

    Ich habe das gerade getestet, und wie es aussieht schreibt Zeile 2 den Wert an der 7.ten stelle in die erste Stelle des Arrays.
    Das bedeutet doch soviel, dass a irgendwie auf das erste Element des Arrays zeigen muss? Falls a kein Pointer ist, wieso kann man es dann derefernzieren? Und wenn dieses a nicht genau auf das erste Element im Array zeigen würde, wieso funktioniert das dann?

    Desweiteren wird bei Zeile 3 dem Element an 7ter Stelle die Adresse des 1 Elements zugewiesen, was noch ein weiteres Argument ist...

    Das ganze verwirrt mich langsam wirklich ein wenig...



  • kaenzign schrieb:

    Danke für die schnellen Antworte, jetzt wird mir das ganze langsam klarer.

    Hier noch ein kurzes Beispiel zur selben Thematik:

    int a [8] = {2,4,6,8,10,12,14,16};
        *a = a[6];
        a[6] = (int)a;
    

    Ich habe das gerade getestet, und wie es aussieht schreibt Zeile 2 den Wert an der 7.ten stelle in die erste Stelle des Arrays.
    Das bedeutet doch soviel, dass a irgendwie auf das erste Element des Arrays zeigen muss? Falls a kein Pointer ist, wieso kann man es dann derefernzieren?

    Automatische Konvertierung zu einem Zeiger int*. a ==> int* tmp ==> dann machst du dein *tmp = a[6].



  • kaenzign schrieb:

    a[6] = (int)a;
    

    Das lässt du am besten bleiben. reinterpret_cast ist böse und fehleranfällig.



  • Hier nochmal der wesentliche Satz, den du wohl überlesen hast... 😉

    dot schrieb:

    a kann lediglich implizit in einen Pointer auf das erste Element umgewandelt werden [...]


  • Mod

    Zeile 2: Array to pointer decay! Taucht ein Array an einer Stelle auf, an der ein Array nicht stehen kann, dann kann es implizit (also ohne Casts durch den Programmierer) in einen Pointer auf sein erste Element konvertiert werden. Das passiert hier in Zeile 2. Den Pointer dereferenzierst du, bekommst dadurch also Zugriff auf das erste Element und dem weist du dann den Wert des 7. Elementes zu.

    Zeile 3:
    Da konvertierst du einen Pointer in einen int. Das geht einmal allgemein gar nicht und wird auf vielen Systemen mit einem Compilerfehler quittiert, weil der Compiler trotz eines C-Casts (nimm doch endlich C++-Casts!) nicht passend machen kann, was nicht passend ist.
    Falls du eines der Systeme hast, bei denen das passt, steht da praktisch:

    a[6] = reinterpret_cast<int>(a);
    

    Wieder zerfällt a zu einem Zeiger auf sein erstes Element. Von diesem Zeiger wird der Zahlenwert a[6] zugewiesen. Der Wert dieses Zeigers hat nichts, absolut gar nichts mit dem Wert von a[0] zu tun! Falls da bei dir tatsächlich 12 heraus gekommen sein solltest, dann geh auf der Stelle Lotto spielen, denn bei dir ist der Zufall kaputt.
    (Ich vermute mal eher, du hast uns anderen Code gezeigt, als bei dir steht).


Anmelden zum Antworten