Funktion definieren, um ein Array dynamisch anzulegen



  • Hallo,

    ist es möglich in C eine Funktion zu definieren, die zur Laufzeit ein Feld mit meinen Spezifikationen aufspannt.
    Genauer stelle ich mir vor, dass ich der Funktion den Datentyp des Arrays mitgebe, den Namen des Arrays und die Dimensionen. Aber ich habe keine Idee, wie man so etwas mit Pointern macht....



  • Stichwort malloc . Aber mit den Datentypen bist du in C leider ein wenig knapp bedient 😉



  • Wie genau meinst Du das? Die Funktion sollte z.B. in der Lage sein, ein Array für int, char, double, float anlegen zu können. Ist das möglich



  • Phil270307 schrieb:

    Wie genau meinst Du das? Die Funktion sollte z.B. in der Lage sein, ein Array für int, char, double, float anlegen zu können. Ist das möglich

    Ja. Aber C ist nicht gerade für Typsicherheit bekannt.

    int *a = malloc(sizeof(int) * anz_elemente);
    double *b = malloc(sizeof(double) * anz_elemente);
    

    Und bitte free nicht vergessen, sobald du den Speicher nicht mehr brauchst. Sonst gibts irgendwann keinen mehr 😉

    MfG



  • Phil270307 schrieb:

    Wie genau meinst Du das? Die Funktion sollte z.B. in der Lage sein, ein Array für int, char, double, float anlegen zu können. Ist das möglich

    Das wäre eher ein Fall für templates in C++, in C kriegst du sowas nicht hin, glaube ich (ich lasse mich gerne eines Besseren belehren). Und nebenbei: den Namen eines Arrays kannst du sowieso nicht dynamisch gestalten. Den gibt es ja nur für dich als Programmierer, in der fertigen exe steht er nicht mehr drin. Mal eine Frage: in welchem Zusammenhang brauchst du das denn bzw. meinst, es zu brauchen? Das kriegt man sicher auch anders hin.

    EDIT: Ok, mit viel Gefrickel würde man sowas in der Art vielleicht doch hinkriegen, aber besonders komfortabel ist eine solche Funktion nicht. Du müsstest deinen Zeiger dann nach void** casten, irgendwie den Typen übergeben oder die Gesamtlänge vor dem Aufruf selbst ausrechnen (sizeof(x)*elements)... Außerdem verleitet eine solche Funktion vielleicht dazu, das free schon mal zu vergessen. Hm, ich würd's lassen...



  • Wo ist das Problem? Das macht man einfach mit malloc(). Typsicherheit sehe ich hier nicht wirklich als Problem. Außerdem sollte ein malloc. Aufruf so aussehen:

    T *foo = malloc (sizeof *foo * n);
    


  • Und wenn das ganze in mehreren Dimensionen in einer Funktion erfolgen soll?





  • Hallo,

    ich habe mir nun eine Funktion gebaut, die ein 1D-Array dynamisch aufspannt - Allerdings ist mir noch nicht klar, ob der allokierte Speicher dem Hauptprogramm sowie den erforderlichen Unterprogrammen zur Verfügung steht.

    Meine Frage:
    + Ich möchte die Speicherallokierung zentral in einer Funktion ablegen, da ich eine größere Menge Daten zu verwalten habe. Demnach müssten doch die Variablen global definiert werden, damit sie per #include den entsprechenden Unterprogrammen zugänglich werden?!?! Nachteil: Verletzung der modularen Programmierung. Gibt es andere/bessere Wege?

    int allocmem(struct myDataType *ptr, int elements) {
      int msg;
    
      ptr = malloc(rows * sizeof(struct myDataType));
      return msg;
    }
    


  • Phil270307 schrieb:

    Allerdings ist mir noch nicht klar, ob der allokierte Speicher dem Hauptprogramm sowie den erforderlichen Unterprogrammen zur Verfügung steht.

    das geht. einmal ge'malloc'ter speicher ist global und während der ganzen programmlaufzeit gültig, bis man ihn mit 'free' wieder wegschmeisst.

    Phil270307 schrieb:

    + Ich möchte die Speicherallokierung zentral in einer Funktion ablegen, da ich eine größere Menge Daten zu verwalten habe. Demnach müssten doch die Variablen global definiert werden, damit sie per #include den entsprechenden Unterprogrammen zugänglich werden?!?! Nachteil: Verletzung der modularen Programmierung. Gibt es andere/bessere Wege?

    du kannst ja den pointer weitergeben. grob betrachtet: z.b. ein modul verwaltet den speicher (malloc/realloc/free) und verteilt 'benutzerrechte', indem es den pointer rumreicht.
    🙂



  • Hi,

    ist dynamisch angelegter Speicher (malloc) wirklich global für alle Module?

    Könnte mir jemand mal bitte ein Beispiel geben, wie man an eine Funktion "bspfunk" ein 2D-Feld übergibt, welches dynamisch allokiert wurde. In der Funktion würde ich gerne mit Indizes auf das Feld zugreifen.

    Besten Dank





  • aha,

    ich habe folgendes probiert:

    #include <stdio.h>
    #include <stdlib.h>
    
    void fun(int **intarray, int rows, int cols);
    
    int main(void) {
      int dimi, dimj;
      int i,j;
      int **array;
    
      printf("Dimension i: ");
      scanf("%d", &dimi);
      printf("Dimension j: ");
      scanf("%d", &dimj);
    
      array = malloc(dimi * sizeof(int*));
      for (i=0; i<dimi; i++) {
        array[i] = malloc(dimj * sizeof(int));
      }
    
      for (i=0; i<dimi; i++) {
        for (j=0; j<dimj; j++) {
          array[i][j] = j + i*dimi;
        }
      }
    
      for (i=0; i<dimi; i++) {
        for (j=0; j<dimj; j++) {
          printf("array[%d,%d]: %d ", i+1, j+1, array[i][j]);
        }
        printf("\n");
      }
    
      fun(array, dimi, dimj);
    
      for (i=0; i<dimi; i++) {
        for (j=0; j<dimj; j++) {
          printf("array[%d,%d]: %d ", i+1, j+1, array[i][j]);
        }
        printf("\n");
      }
      free(array);
      return 0;
    }
    
    void fun(int **intarray, int rows, int cols) {
      intarray[rows][cols] = 1000;
    }
    

    Das war allerdings nicht erfolgreich. "./bsp2.make: line 5: 11461 Speicherzugriffsfehler bsp2.exe".

    In einem anderen Bsp habe ich gelesen, das malloc wie folgt verwendet werden soll, um ein 2D-array aufzuspannen:

    int **array = malloc(zeilen*sizeof(int**));
    

    das verstehe ich aber nicht. Ich hätte sizeof(int*) verwendet....



  • Phil270307 schrieb:

    In einem anderen Bsp habe ich gelesen, das malloc wie folgt verwendet werden soll, um ein 2D-array aufzuspannen:

    int **array = malloc(zeilen*sizeof(int**));
    

    das verstehe ich aber nicht. Ich hätte sizeof(int*) verwendet....

    schmeiss das beispiel in die tonne und machs richtig. 😃
    in dem fall sollte es aber egal sein, weil sizeof(int*) und sizeof(int**) beide gleich gross sind, somit liefert zeilen*sizeof(int**) == zeilen*sizeof(int*) == 4 bytes. 🙂



  • Phil270307 schrieb:

    Und wenn das ganze in mehreren Dimensionen in einer Funktion erfolgen soll?

    mehrdimensionale arrays mit zeiger a la int** int*** etc sind vor allem bei sehr vielen arrayelementen ineffizient, weil etliche (mega/giga) bytes nur für die zeiger verschwendet werden.
    jede n-dimensionale tabelle lässt sich auf ein eindimensionales array vom typ E* zurückführen.
    E == egal was fürn typ. 🙂



  • Phil270307 schrieb:

    Wie genau meinst Du das? Die Funktion sollte z.B. in der Lage sein, ein Array für int, char, double, float anlegen zu können. Ist das möglich

    jo, ist möglich, guckst du:

    #define INT   0
    #define PINT  1
    #define CHAR  2
    #define PCHAR 3
    
    void* my_malloc_factory ( unsigned type, unsigned n )
    {
    	switch (type)
    	{
    		case INT:
    			return malloc ( sizeof(int) * n );
    		break;
    
    		case PINT:
    			return malloc ( sizeof(int*) * n );
    		break;
    		//...
    		case PCHAR:
    			return malloc ( sizeof (char*) * n );
    		break;
    
    		default:
    			return NULL;
    		break; 
    	}
    }
    
    int main ()
    {
    	int* pint = my_malloc_factory ( INT, 100 );
    	int** ppint = my_malloc_factory ( PINT, 100 );
    	char** ppchar = my_malloc_factory ( PCHAR, 100 );
    
    	free (pint);
    	free (ppint);
    	free (ppchar);
    
    	return 0;
    }
    

    die fehermeldung-/behandlung, die noch fehlt habe ich mir gespart. die würd ich in etwa so machen tun:

    void* my_malloc_factory ( unsigned type, unsigned n )
    {
    	void* my_multipointer = NULL;
    	switch (type)
    	{
    		case INT:
    			if ( NULL == (my_multipointer = malloc ( sizeof(int) * n )))
    				fprintf ( stderr, "%s\n", strerror(errno));
    			return my_multipointer;
    			return malloc ( sizeof(int) * n );
    

    und in main:

    int* pint = my_malloc_factory ( INT, 100 );
    
    	if (pint == NULL )
    		// nach hause gehen, oder sonst was :)
    

    gruß,
    l.n.



  • ist dein Motto "Warum einfacher, wenn es schwerer geht?"

    Die einfachste Methode:

    T *array;
    
    array = malloc(elements * sizeof *array);
    

    wobei T frei wählbar ist und an sich die einzige Codezeile, die verändert werden muss.



  • schon klar, aber der OP wollte eine funktion für alle möglichen typen, bei deinem T kann das in eine casting orgie ausarten.



  • Ich sehe keine Casting-Orgie. Noch nichtmal eine Cast-Orgie.



  • list n00b schrieb:

    schon klar, aber der OP wollte eine funktion für alle möglichen typen, bei deinem T kann das in eine casting orgie ausarten.

    Wenn ich meinen letzten Beitrag anschaue, dann kann ich nur Tims Worte wiederholen: Ich sehe keine Casting-Orgie. Noch nichtmal eine Cast-Orgie.


Anmelden zum Antworten