Wozu Arrays in C++`??



  • Hallo"

    Dummer Titel, aber egal. Mir ist letztens aufgefallen, dass sowas hier geht:

    int* i;
    i[2]=7;
    

    Also kann man mit einem einfachen Zeiger ein Array erzeugen. Wozu brauch ich denndann noch den umständlicheren Befehl hier:

    int array[23]; ///?????

    Ich meine, es geth doch auch mit einfachen Zeigern, oder nicht?

    Gruß, Maxi



  • Warum so umständlich und unflexiebel mit nem Pointer? Man kann ja auch std::vector nehmen! 😉 Find ich allen deinen zwei Varianten vorzuziehen, wenn man schon so redet.

    Im ernst, man nimmt das was man gerade braucht.



  • Ich glaube er hat noch nicht mal realisiert das man auch Speicher holen muss.



  • Interessante Methode, ein Array zu "erzeugen"!



  • Der speicher gehört dir vielleicht garnicht!!!



  • Schwachsinn

    [ Dieser Beitrag wurde am 24.03.2003 um 15:41 Uhr von MaSTaH editiert. ]



  • Dummer Titel, aber egal. Mir ist letztens aufgefallen, dass sowas hier geht:
    int* i;
    i[2]=7;

    Das einzige was hier geht ist die Korrektheit des Programms. Und zwar den Bach runter.
    Ist aber ne schöne Art und Weise undefiniertes Verhalten zu erzeugen.



  • OK, Sorry. Ihr redet, als ob ich ein Anfänger(was ich ja auch bin) wär und überhaupt keine Peilung von C++ hab. Also, bis jetzt hab ich keine Begründung geört, warum das Programm den Bach runtergeht. HM, vielleicht deswegen:

    Wenn ich das so erzeuge:

    int * i;
    i[2]=7;

    wird nur Speicher für ein Int-Element freigegeben. Wenn ich dann auf das zweite zugreife, so geht das, aber es kann sein, dass wenn ich dann einen zweiten Pointer erstelle:

    int* j;
    , dass dieser Pointer auf i[2] zeigt. Wenn ich dann also *j verändere, ändert sich auch automatisch i[2].

    Verhält saich das so?
    Wenn ja, dann kann man das aber aucvh ausnutzen: Wenn man nicht direkt auf irgendwelche Adressen im speichedr zugreifen kann, so kann man meinetwegen davor zugreifen und dann mit dem Index auf den Speicher zugreifen. Oder spuckt Windows da nen Fehler aus??

    Gruß, Maxi



  • Also:

    int *i;  //zeigt ihrgendwo hin, weil nicht initialisirt
             //es wird auch kein Speicher für einen Int zur Verfügung gestellt
    
    i[2] = 7;//der Zeiger zeigt immer noch nach ihrgendwo plus Zwei sizeof(Int)
             //Frage: Wer weiß was sich dort befindet?
    

    Folgerung: undefiniertes Verhalten



  • Original erstellt von Maxi:
    OK, Sorry. Ihr redet, als ob ich ein Anfänger(was ich ja auch bin) wär und überhaupt keine Peilung von C++ hab.

    Kein Kommentar.

    **Wenn ich das so erzeuge:

    int * i;
    i[2]=7;

    wird nur Speicher für ein Int-Element freigegeben.**

    Hier wird überhaupt nichts freigegeben. Du deklarierst einen Pointer, der auf eine nicht vorhersehbare Speicherposition zeigt, da er nicht initialisiert ist. Dann schreibst du dort in der Nähe (2*sizeof(int) Bytes weiter) eine 7 hin. Da du keine Kontrolle über den Zeiger hast, könnte das zb im Betriebssystemkern sein. Oder über irgendeiner anderen Variable von dir. Oder im Puffer eines Streams. Oder über einer Rücksprungadresse einer Funktion. Du mußt als Programmierer sicherstellen, dass ein Zeiger, über den du eine Speicherstelle beschreibst oder ausliest, auf Speicher verweist, der auch zum lesen oder schreiben vorgesehen ist. Niemand nimmt dir das ab.

    Den Rest kommentier ich mal nicht, da das dein Kern-Mißverständnis ist.



  • aber der Pointer
    int* i;

    zeigt auf eine bestimmte Adresse, die von keinem anderen Programm, von keiner anderen Variable überschrieben werden kann oder muss ich dem auch noch ne Adresse zuweisen, etwa so:
    int* I = 0xCC5F6E34 //oder ähnlich
    aber so was hab ich noch nie gesehen.

    Gruß, MAxi



  • Worauf zeigt denn

    int *i;
    

    ???

    int* I = 0xCC5F6E34 //oder ähnlich

    Damit würdest du I den Wert 3428806196 zuweist, wenn I auf einen von dir
    angeforderten Speicher zeigen würde.



  • Original erstellt von Maxi:
    *aber der Pointer
    int
    i;

    zeigt auf eine bestimmte Adresse, die von keinem anderen Programm, von keiner anderen Variable überschrieben werden kann**

    Wie kommst du darauf?

    **
    oder muss ich dem auch noch ne Adresse zuweisen, etwa so:
    int* I = 0xCC5F6E34 //oder ähnlich
    aber so was hab ich noch nie gesehen.**

    Wenn du wüßtest, das an dieser Adresse gerade mal Platz ist, kannst du das gerne machen. Das weißt du aber nicht. Deshalb weist du einem Pointer nur folgende Sachen zu:

    • einen anderen Pointer: p = q + 3; z.b.
    • die adresse eines Objektes: p = &a;
    • den Nullpointer: p = 0;
    • eine in einem Header definierte Zeigerkonstante: p = SIG_IGN;
    • das Ergebnis des new-Operators oder der malloc-Funktion


  • int *i;
    der zeiger i zeigt irgendwo in den speicher. womöglich in einen teil des speichers, den du nicht lesen darfst.
    du kannst dem zeiger eine bestimmte adresse so zuweisen

    int *i = reinterpret_cast<int*>(123456789);
    

    Allerdings weißt du auch nciht, was sich hinter der speicheradresse 123456789 verbirgt.
    richtige wege sind zb:

    int x; //normale variable (speicher wird erzeugt)
    int *i = &x; //i nimmt die adresse von x ,  und das ist eine gültige
    int *i2 = new int; //hole neuen speicher vom heap
    //nicht vergessen:
    delete i2;
    

    andere siehe bashar weiter unten (wahrsagerkugel 😃 )

    [ Dieser Beitrag wurde am 24.03.2003 um 19:34 Uhr von Noesis editiert. ]



  • Achso, also ist es eigentlich falsch, nur mit einfachen Pointern zu arbeiten, die meinetwegen ´nur ein int sind und so definiert sind:

    int* i;

    Das heißt, die knnen ganz gefährlich sein?

    Ich benutze eigetnlich sowas nie, außer um in Klassen die Adressen anderer zu speichern und dann auf die Meberfunktionen der gespeicherten Klasse zuzugreifen. Ansonsten nutze ich keine Zieger.



  • Original erstellt von Bashar:
    **

    • einen anderen Pointer: p = q + 3; z.b.
    • die adresse eines Objektes: p = &a;

    **

    Das aber auch nur wenn du vorher Speicher nach q angeforerst hast
    z.B.:

    int *p;
    int q[5]={0,1,2,3,4};
    p = q + 3; //p zeigt auf 3
    
    //oder
    
    int *p;
    int *q;
    q = new int[5];
    
    for(int temp=0; temp <= 4; ++temp)
       q[temp] = temp;
    
    p = q[3]; //p zeigt wieder auf 3
    delete[] q;
    

    [ Dieser Beitrag wurde am 24.03.2003 um 19:37 Uhr von C Newbie editiert. ]



  • @Maxi
    Zeiger können in aller Regel sehr gefährlich sein, da man problemlos in die Speicherbereiche anderer Programme reinpfuschen kann (sofern das OS dies nicht unterbindet). Unter Windows bekommt man beim Zugriff auf fremden Speicher eine "Access Violation"-Nachricht und das Programm stürzt ab. Wenn man nicht aufpasst ist so ein Fehler schwer zu finden, da er erst zur Laufzeit auftritt... Meiner Meinung nach sollte man da wo es realisierbar ist mit Referenzen arbeiten... auto_ptr sind auch interessant wenn man Speicher auf dem Stack anfordert, aber manchmal kommt man um Pointer nicht herum, z.B. wenn man den Zeiger auf ein Objektes in einer Membervariable speichern will

    [ Dieser Beitrag wurde am 24.03.2003 um 20:07 Uhr von MaSTaH editiert. ]



  • Zeiger sind nicht in aller Regel gefährlich wenn man richtig damit umgeht!

    [ Dieser Beitrag wurde am 24.03.2003 um 22:43 Uhr von Lars editiert. ]



  • gefaehrlich bedeutet, die chance ist erhoerht, damit falsch umzugehen.
    ein pointer kann nicht auf eine klasse zeigen. nur auf ein objekt.



  • ganz einfach 🙂

    wenn DU einen Zeiger erstellst, zeigt der Prinzipiell erst mal ins Nirvana ....
    (bei M$ : #define nirvana 0xcdcdcdcd 😃 )
    dort steht sonstwas, nur nix brauchbares oder ungefaehrliches 🙂

    Deshalb ist es guter Stil, zeiger immer gleich zu inititalisieren,
    wenn Du die Adresse (noch) nicht weisst, nimmst du NULL !
    also int * pInt = NULL ; Das erkennt der compiler und motzt, wenn du an dieser Adresse was versuchst zu veraendern !!!

    Zeiger sind natuerlich nur nuetzlich, wenn DU die Adressen weisst. die wirst aber nie in ihrer numerischen Form benutzen .... das ist zu umstaendlich und fehlertraechtig .... also "int *i = reinterpret_cast<int*>(123456789);" ist zwar technisch moeglich, aber nich wirklich elegant ....

    Heisse Kandidaten zum holen von Adressen sind :
    - der AdressOf-Operator "&"
    - der "new" Operator
    - und, logisch, andere Zeiger .....

    Fuer den Umgang mit Waffen braucht man meist nen Waffenschein, fuer den Umgang mit Zeigern sollte man zumindest mal die Toutorials gelesenen haben 😃 😃 😃

    Ciao ...


Anmelden zum Antworten