PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] realloc zweidimensionals Array



V:X
03.07.2011, 13:37
Hi zusammen,

ich hoffe, meine Frage ist hier richtig. Es geht um ein generelles Problem in C, nicht in Bezug auf spezielle Hardware/µC.
Ich versuche mich gerade an der dynamischen Speicherverwaltung mit zweidimensionalen Arrays. Durch googlen hab ich das mit malloc super hingekriegt. Jetzt will ich das Array aber auch vergrößern und verkleinern, also mit realloc arbeiten. Dazu hab ich leider nichts gefunden, dass mir wirklich weiterhelfen würde.
Mein Code sieht aktuell so aus:



void main(void){
int i, j;
double **testarray = NULL;

testarray = (double**) realloc(testarray, 5 * sizeof(double*));

for (i = 0; i < 5; i++){
if(testarray[i] = (double*) realloc(testarray, 5 * sizeof(double)) == NULL)
printf("\nFEHLER\n");
else
printf("\nOK\n");
}


// Werte in gerade vergrößertes Array schreiben
for(i=0; i<5; i++){
for(j=0; j<5; j++){
testarray[i][j] = i+j;
}
}

// Ausgabe
for(i=0; i<5; i++){
for(j=0; j<5; j++){
printf("testarray[%i][%i] = %f\n", i, j, testarray[i][j]);
}
}

}


Ich bekomme auch fünfmal "OK" angezeigt, aber wenn dann Werte in das Array geschrieben werden sollen, stürzt das Programm ab.
Was mache ich falsch?

Danke schonmal für jeden Tip!

Schönen Sonntag,
V:X

sternst
03.07.2011, 15:39
1) Du hast da gar kein zweidimensionales Array. Du hast mehrere eindimensionale Arrays und ein zusätzliches Array mit Zeigern auf die Arrays. Der Zugriff sieht zwar genauso aus, aber das Layout im Speicher ist gänzlich anders. Und dementsprechend sähe ein Vergrößern eines "echten" zweidimensionalen Arrays auch ganz anders aus.

2)

if(testarray[i] = (double*) realloc(testarray, 5 * sizeof(double)) == NULL)Hier müsste es eigentlich "realloc(testarray[i]," heißen.

3) Punkt 2 löst dein Problem aber nicht vollständig. Du darfst als ersten Parameter an realloc nur einen Pointer übergeben, den eine der *alloc-Funktionen geliefert hat, oder Null. Du übergibst in der Schleife aber uninitialisierten Müll an realloc. Nach dem realloc des Pointer-Arrays musst du die neuen Pointer erst mal Nullen.

V:X
03.07.2011, 17:57
Danke für die schnelle Antwort!

Aber leider stürzt mein Programm immer noch ab. Ich hab den Schleifeninhalt jetzt so geändert, dass ein mit NULL initialisierter Pointer übergeben wird:



for (i = 0; i < 5; i++){
testarray[i] = NULL;
if( testarray[i] = (double*) realloc(testarray[i], 5 * sizeof(double)) == NULL)
printf("\nFEHLER\n");
else
printf("\nOK\n");
}


Ich erhalte auch immer die folgende Warnung:


warning: assignment makes pointer from integer without a cast

Damit kann ich nicht viel anfangen. Ich erstelle doch gar keinen int-Poiter?

Ich würd mich freuen, wenn ihr mir nochmal auf die Sprünge helfen könntet!

Danke schonmal und schönen Abend noch,
V:X

sternst
03.07.2011, 22:07
Ich erhalte auch immer die folgende Warnung:


warning: assignment makes pointer from integer without a cast

Damit kann ich nicht viel anfangen. Ich erstelle doch gar keinen int-Poiter?Das behauptet die Warnung ja auch gar nicht. Sie behauptet, dass du mittels einer Zuweisung aus einem Integer direkt (ohne expliziten Cast) einen Pointer machst. Und sie hat Recht. In dieser Zeile

if( testarray[i] = (double*) realloc(testarray[i], 5 * sizeof(double)) == NULL)fehlt eine Klammerung.


PS: Und noch was Grundsätzliches: warum steht in deinem ersten Post nichts von der Warnung?
Warnungen ignoriert man nicht einfach, erst recht nicht, wenn man sie nicht versteht. Und wenn du in einem Forum wegen einem Code-Problem nachfragst, dann schreibe auch dazu, was der Compiler zu dem Code zu sagen hat. Für andere können die Warnungen schließlich wertvolle Hinweise enthalten.

V:X
04.07.2011, 20:17
Schau an, die fehlende Klammerung war die Lösung! Danke für den Hinweis!

Hast ja Recht, wegen der Warnung. Aber das ist jetzt echt der erste Fall, wo mir eine Warnung wirklich an einer "funktionskritischen" Stelle erscheint. Bisher hab ich nur Warnungen erlebt mit einer Wichtigkeit von "Variable XY ist angelegt, wird aber nie verwendet". Sprich, die erschienen mir bisher einfach wenig wichtig. Aber da bin ich wohl nicht der erste ;)

Aber so 100%ig hab ich das jetzt noch nicht verstanden. Ich würde jetzt meinen, dass durch

if( testarray[i] = (double*) realloc(testarray[i], 5 * sizeof(double)) == NULL)
keine klare Trennung zwischen Zuweisung und Vergleich gegeben ist. Und dann kommt es bei der Programmausführung zu einem (Speicher?-) Fehler, was durch die zusätzliche Klammerung wiederum verhindert wird.

Und du hast geschrieben, dass ich

mittels einer Zuweisung aus einem Integer direkt (ohne expliziten Cast) einen Pointer
mache. Aber oben habe ich doch
double **testarray deklariert. Dann ist es doch ein double-Zeiger auf einen Speicherbereich, in dem ich weitere double-Zeiger habe. Die ich erweitern und daher wie ein Array verwenden kann. Oder nicht?
Mir ist noch nicht klar, wo bei der Sache "auf einmal" das Integer herkommt.

Danke schonmal für jeden Denkanstoß!
V:X

sternst
05.07.2011, 00:02
Ich würde jetzt meinen, dass durch
if( testarray[i] = (double*) realloc(testarray[i], 5 * sizeof(double)) == NULL)keine klare Trennung zwischen Zuweisung und Vergleich gegeben ist.Warum? Was genau soll denn diese "klare Trennung" sein?

Zwei Dinge sind dir hier offenbar noch nicht klar:
1)
==, != , <, >, das sind alles ganz normale Operatoren, wie +, -, *, etc. Es gibt da keinen Unterschied.
2)
Es gibt auch keinen besonderen Zusammenhang zwischen dem if und diesen Operatoren. Dem if ist es völlig egal, was genau da in der Klammer steht. Zuerst wird der Ausdruck in der Klammer komplett ausgerechnet, und für das if ist dann nur das Endergebnis dieser Berechnung von Interesse. Nämlich ob es 0 oder nicht 0 ist.

Bei deiner Zeile stehen also einfach nur drei Operanden mit zwei Operatoren dazwischen:
A = B == CDa es keine Klammern gibt, regelt die Operator-Precedence in welcher Reihenfolge das ausgewertet wird. Und da der ==-Operator eine höhere Präzedenz hat (man kann auch sagen: bindet stärker) wird zuerst der Vergleich B == C ausgewertet. Das Ergebnis davon wird dann an A zugewiesen. Und das Ergebnis der Zuweisung ist dann das, was das if auswertet. Das Ergebnis des ==-Operators ist übrigens ein Integer, der entweder 0 (nicht gleich) oder 1 (gleich) ist. Und daher auch die Warnung: dem Pointer A wird ein Integer (Ergebnis von B == C) zugewiesen.

V:X
05.07.2011, 21:27
Da es keine Klammern gibt, regelt die Operator-Precedence in welcher Reihenfolge das ausgewertet wird. Und da der ==-Operator eine höhere Präzedenz hat (man kann auch sagen: bindet stärker) wird zuerst der Vergleich B == C ausgewertet. Das Ergebnis davon wird dann an A zugewiesen. Und das Ergebnis der Zuweisung ist dann das, was das if auswertet. Das Ergebnis des ==-Operators ist übrigens ein Integer, der entweder 0 (nicht gleich) oder 1 (gleich) ist. Und daher auch die Warnung: dem Pointer A wird ein Integer (Ergebnis von B == C) zugewiesen.

Jetzt ist der Groschen gefallen!!
Vielen Dank für die Hilfe und abschließende Erklärung!

Grüße,
V:X