Zusammenhängender Speicher bei mehrdim. Arrays?



  • Hi,

    ich weiß jetzt nicht, wie du das mehrdimensionale Array
    allozieren möchtest.

    Im Allgemeinen geht soetwas hier nicht:

    int **a = malloc(5*4*sizeof(int));
       for (int x = 0; x < 5; ++x)
          for (int y = 0; y < 4; ++y)
              a[x][y] = x+y;
    

    Mehrdimensionale Arrays legt man eher wie folgt an:

    int **a = malloc(5*sizeof(int*));
       for (int x = 0; x < 5; ++x) a[x] = malloc(4*sizeof(int));
       for (int x = 0; x < 5; ++x)
          for (int y = 0; y < 4; ++y)
              a[x][y] = x+y;
    

    Bei dieser Variante befinden sich die Element nicht zwingend
    zusammenhängend im Speicher, wobei jede Zeile für sich genommen schon.

    Möchtest du nun, dass der benötigte Speicher zusammenhängt ist,
    musst du die Adressierung von Hand machen, so z.B.:

    int *a = malloc(5*4*sizeof(int));
       for (int x = 0; x < 5; ++x)
          for (int y = 0; y < 4; ++y)
             a[x*4+y] = x+y;
    

    Bitte korrigiert mich, sollte ich noch eine Möglichkeit
    übersehen haben.

    Gruß mcr

    EDIT: da war mal wieder einer schneller 🙂



  • Bashar schrieb:

    Da mehrdimensionale Arrays in C nicht existieren

    Im Standard werden sie aber so genannt 😉



  • Aus 6.5.2.1§3 hätte man auch eine nicht-normative Anmerkung machen können.



  • Sei zB int array[2][3] mit bel. Elementen gebeben.

    Wenn ichs 6.5.2.1 richtig entnehme, so ist im oberen Bsp. array[2][1] äquivalent zu *(array+4).
    Rischtösch?



  • papiertaschentuch schrieb:

    Rischtösch?

    😕



  • papiertaschentuch schrieb:

    Sei zB int array[2][3] mit bel. Elementen gebeben.
    Wenn ichs 6.5.2.1 richtig entnehme, so ist im oberen Bsp. array[2][1] äquivalent zu *(array+4).

    glaub ich nicht, weil *array ja ein int[3] wäre. wenn du's nach 'int*' castest, dann müsste es das sein:

    *((int*)array+2*3+1) // zweite spalte, erste zeile
    

    🙂



  • +fricky schrieb:

    papiertaschentuch schrieb:

    Sei zB int array[2][3] mit bel. Elementen gebeben.
    Wenn ichs 6.5.2.1 richtig entnehme, so ist im oberen Bsp. array[2][1] äquivalent zu *(array+4).

    glaub ich nicht, weil *array ja ein int[3] wäre. wenn du's nach 'int*' castest, dann müsste es das sein:

    *((int*)array+2*3+1) // zweite spalte, erste zeile
    

    🙂

    ((array+1)+0) wäre das dann wohl ganz richtig, nehm ich an. Zumindest klappt das unter VS08.

    Was mich aber äußerst verwirrt ist folgendes:

    Ich habe in C in einem struct ein 2-dim-array erstellt und es an ein Assembler-Unterprogramm übergeben, und zwar: asm_programm(struct* struct_matrix)

    Nun lade in Assembler einfach die Adresse des Array im Struct in ein Register, greiffe auf den Inhalt der adressierten Speicherstelle zu (also das jeweilige Array-Element), bearbeite ihn, wie mir passt und erhöhe den Wert der besagten Adresse um 4Byte (int), um stets zum nächsten Element zu gelangen. Und es klappt...



  • papiertaschentuch schrieb:

    ((array+1)+0) wäre das dann wohl ganz richtig, nehm ich an. Zumindest klappt das unter VS08.

    das sieht schon besser aus. auf dein beispiel bezogen müsste es aber ((array+2)+1) sein, nehme ich an.

    papiertaschentuch schrieb:

    ...und erhöhe den Wert der besagten Adresse um 4Byte (int), um stets zum nächsten Element zu gelangen. Und es klappt...

    naja, weil eben die 2 mal int[3] direkt hintereinander liegen. was für C ein 2-d array ist, nimmt deine asm-routine eindimensional wahr. und dieses ((array+2)+1) sieht zwar aus wie ein pointer-auf-pointer zugriff, ist es aber nicht.

    int array[2][3];
    int **q = (int**)array;
    
    *(*(array+2)+1) = 123;  // OK, compiler weiss, dass es ein array ist und rechnet dementsprechend die zieladresse aus.
    *(*(q+2)+1) = 123;      // *peng*, compiler behandelt es als int** und rechnet anders.
    

    🙂



  • Ach ja...

    int *ptr = &array[0][0];
    
    //*(ptr+0) == erstes Element
    //*(ptr+1) == zweites Element
    //*(ptr+5) == letztes Element
    

    tuts dann wohl auch.

    Wozu eigentlich so ein Gefrickel seitens des Standards?



  • wozu überhaupt ein gefrickel mit mehrfachpointern.
    int [x*y*z] oder malloc(x*y*z*sizeof(int)) tuts ja auch.
    die addresierung ist ja auch dann machbar.



  • antifrickelfan schrieb:

    wozu überhaupt ein gefrickel mit mehrfachpointern.
    int [x*y*z] oder malloc(x*y*z*sizeof(int)) tuts ja auch.
    die addresierung ist ja auch dann machbar.

    adressierung machbar, aber ab 3D aufwärts gar nicht mehr soooo einfach.
    🙂



  • adressier n00b schrieb:

    adressierung machbar, aber ab 3D aufwärts gar nicht mehr soooo einfach.
    🙂

    Soo schwer aber auch nicht.
    Für 3D:
    Index = z*(xmax+1)(ymax+1) + y(xmax+1)+x
    oder mit den Buchstaben a,b,c:
    Index = c*(amax+1)(bmax+1) + b(amax+1)+a
    Für vier Dimensionen:
    Index = d*(amax+1)(bmax+1)(cmax+1) + c*(amax+1)(bmax+1) + b(amax+1) + a

    Das Bildungsgesetz für höhere Dimensionen kann man davon ableiten.


Anmelden zum Antworten