Array an Funktion übergeben/Arraylänge ermitteln
-
Ich habe mich gefragt, ob es Möglichkeiten gibt, ein Array an eine Funktion zu übergeben, ohne dass dabei das Array in Gefahr gerät, geändert zu werden.
Aktuell übergebe ich einer Funktion einen Pointer, woraufhin jede Änderung des Arrays unmittelbar am Original spürbar wird - was allerdings nicht immer erwünscht ist.
Bei kleinen Arrays zerlege ich einfach das Array in die einzelnen Werte und übergebe diese - bei Nutzung einer rekursiven Funktion kann somit jede Ebene der Funktion seine ganz persönliche Variable nutzen. Beim Array geht das leider nicht.
Ich habe auch schon versucht, mein Ausgangs-Array zu kopieren, allerdings ist das ziemlich aufwändig und sowas kann bei größeren Arrays sicher Unmengen an Speicher fressen, zumal es keine maximale Rekursionstiefe gibt.Weiß jemand Abhilfe? Oder geht es wirklich nur, das Array zu kopieren?
------------------
Dann habe ich gleich noch eine Frage: Kann ich bei einem mehrdimensionalen Array die Größe der ersten Dimensionen ermitteln? Also die Länge der Pointer-Arrays? Wenn ich aus dem Array gerate, gibt es ja vermutlich einen Speicherzugriffsfehler. Gibt es einen Weg, das Array sozusagen "abzutasten", sodass dieser Zugriffsfehler zwar registriert wird, aber nicht zum Programmabsturz führt? Oder hilft vielleicht etwas ganz anderes?
-
Eigentlich ist das Keyword 'const' dafür.
void foo(char *x) { *x = 0; } void bar(const char *x) { *x = 0; /* Compilier Fehler */ }
Das Problem mit Zeigern ist, dass du nicht verhindern kannst, dass der Inhalt, worauf die übergegebenen Zeiger zeigen, nicht verändert wird, denn du kannst das 'const' immer wegcasten:
void bad(const char *x) { char *y = x; *y = 0; }
Was auch geht ist wenn der Zeiger auf Read-Only memory zeigt
void test(void) { char hallo[] = "Hallo"; char *bye = "Bye"; bad(hallo); /* hallo == {'\0', 'a', 'l', 'l', 'o', '\0'} */ bad(bye); }
das einzige Blöde: es quittiert 100% mit Segfault, also auch keine Alternative.
Zeiger geben dir viel Macht und Flexibilität, wer aber Macht hat, muss mit Verantwortung umgehen
-
supertux schrieb:
Zeiger geben dir viel Macht und Flexibilität, wer aber Macht hat, muss mit Verantwortung umgehen
Jaja ;).
Das Problem ist ja nicht, dass ich nicht aufpassen kann, was ich mache, sondern dass ich mit dem Array arbeiten muss. Soweit ich bis jetzt weiß, ist eine Änderung unumgänglich - würde sich das ganze wie eine simple übergebene Variable verhalten, wäre das kein Problem. Aber so wird es dann wohl in brutales Rumkopieren ausarten... Vielleicht kann der free-Befehl ja ein wenig Schadensbegrenzung betreiben.
Hast du vielleicht einen Tipp zur Ermittlung der Länge eines Pointer-Arrays? Es wäre praktisch, wenn es da was gäbe.
-
Stiefel2000 schrieb:
Vielleicht kann der free-Befehl ja ein wenig Schadensbegrenzung betreiben.
nein,
free
gibt nur den Speicher frei, verhindert aber nicht, dass du dort nichts mehr schreibst.int *x = calloc(somesize, sizeof *x); if(x == NULL) exit(1); x[somesize / 2] = 4; ... free(x); x[somesize / 2] = 2;
kann sehr böse enden.
Stiefel2000 schrieb:
Hast du vielleicht einen Tipp zur Ermittlung der Länge eines Pointer-Arrays? Es wäre praktisch, wenn es da was gäbe.
es gibt nur eine: die Länge mit dem dem Zeiger übergeben:
void foo(data_type *array, size_t len) { ... }
-
supertux schrieb:
es gibt nur eine: die Länge mit dem dem Zeiger übergeben:
void foo(data_type *array, size_t len) { ... }
Was ich mir angewoehnt habe, ist in solchen Faellen grundsaetzlich mit Listen zu arbeiten - also:
typedef struct data_type { Data my_Data; data_type next = NULL; } void foo(data_type *list) { ... }
Das letzte Element der List pointed auf NULL und damit ist man auf der sicheren Seite.
-
Warte mal. Du benutzt Listen statt arrays um dir einen Parameter im Aufruf zu sparen, den du dir ohnehin sparen kannst wenn du das Array (wie auch deine Liste) in ein struct verpackst?
-
@ supertux: Das mit free war auch so gemeint, dass ich meine ständig duplizierten Arrays in der Anzahl ein wenig eingrenzen kann. Das muss ich nur an der richtigen Stelle anbringen.
@ hartmut1164:
Das mit der Liste ist eine ganz gute Idee, auch wenn ich bisher nur begrenzt was mit Strukturen zu tun hatte. Aber irgendwann komme ich da eh nicht mehr drum herum :).
-
Tim schrieb:
Warte mal. Du benutzt Listen statt arrays um dir einen Parameter im Aufruf zu sparen, den du dir ohnehin sparen kannst wenn du das Array (wie auch deine Liste) in ein struct verpackst?
Nicht nur deshalb - Ich bin damit einfach flexibler; kann leichter Werte einfuegen, neusortieren oder kann die Liste Rueckgabewert einer Einlesefunktion verwenden, die auch gleich den Speicher allociert, sie beliebig verlaengern oder kuerzen etc. pp.
So aus meiner Erfahrung: Man faengt mit einem Array an, dann muss doch noch etwas an einer Position einfuegen, eine weitere Suchordnung einbauen und dann wird es langsam unuebersichtlich. Dann fange ich lieber gleich mit einer verketteten Liste an und spare mir den ganzen Zorres - viel einfacher am Ende.
-
hartmut1164 schrieb:
So aus meiner Erfahrung: Man faengt mit einem Array an, dann muss doch noch etwas an einer Position einfuegen, eine weitere Suchordnung einbauen und dann wird es langsam unuebersichtlich.
Sinnvoller, als einfach "grundsätzlich" Listen zu verwenden, ist aber, sich vorher zu überlegen, welche Datenstruktur in dem konkreten Fall am besten geeignet ist, und dann die zu nehmen.
Und in Grenzfällen würde ich eher das nehmen, was in der betreffenden Programmiersprache einfacher und "natürlicher" einzusetzen ist. In einer funktionalen Sprache sind das Listen, aber in C sind es nunmal Arrays.