Wozu Arrays in C++`??
-
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 zuweisenint *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 ungefaehrlichesDeshalb 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 ...
-
wenn DU einen Zeiger erstellst, zeigt der Prinzipiell erst mal ins Nirvana ....
naja, theroretisch könnte er auch zufällig genau dahin zeigen wo man will:)
Zeiger sind nicht in aller Regel gefährlich wenn man richtig damit umgeht!
was ist schon gefährlich wenn man richtig damit umgeht
[ Dieser Beitrag wurde am 25.03.2003 um 11:24 Uhr von crass editiert. ]
-
Kettensägenjongleure vor!
-
Original erstellt von Lars:
[QB]Zeiger sind nicht in aller Regel gefährlich wenn man richtig damit umgeht!Deswegen habe ich ja geschrieben "können gefährlich sein"... Den Grund dafür siehst du wenn du dir die Fragestellung dieses Threads anguckst. Das ist nämlich gefährlich, da dort nicht richtig damit umgegangen wird...
-
Original erstellt von <XYZ>:
**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 !!!
**Also meinem Compiler ist das egal
Original erstellt von <XYZ>:
**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 ....
**Es ist noch nichtmal technisch realisierbar auf eine feste numerische Adresse zuzugreifen, da sich die Adresse des Objektes nach jedem Programmaufruf ändern kann...
// Dies wird in ca. 1/1000000000000000 Fällen zufällig nicht zum Absturz führen int *p = (int*)0x090DCA64; int i = p[24];
-
Es ist noch nichtmal technisch realisierbar auf eine feste numerische Adresse zuzugreifen, da sich die Adresse des Objektes nach jedem Programmaufruf ändern kann...
Früher unter DOS war sowas mal sinnvoll. an bestimmten adressen waren bestimmte Teile des Betriebssystems. bei 0xb800 lag eine Speigelung des Grafikkartenspeichers, usw. Je nach Plattform für die man programmiert kann es durchaus sinnvoll sein.