Auspannen eines Feldes



  • CStoll schrieb:

    Erstmal ist der Speicher, den du reservieren willst, viel zu klein - da benötigst du "calloc(maxImaxJ,sizeof(struct Coords))". Und zweitens - wo genau gibt es denn den Fehler?
    PS: Auf einzelne Elemente kannst du zugreifen mit "mCoords[i+maxI
    j];"

    Warum wollt ihr denn unbedingt an der Intelligenz des Compilers vorbeiprogrammieren.

    typedef struct tagsCoords 
    {
        double xE;
        double yE;
        double xW;
        double yW;
    } sCoords;
    
    // Anzahl der sCoords-Einträge holen.
    unsigned int cnt = maxx * maxy;
    
    // Speicher allokieren. Ergebniss ist ein Array von SCoords
    sCoords *p_coords = (sCoords*) malloc (sizeof (sCoords)*cnt);  
    
    for (idx = 0; idx < cnt; idx++)
    {
       p_coords[idx].xE = 10;
    }
    

    Der Compiler weiss schon, das mit p_coords++ eine Erhöhung um
    32bit gemeint ist. Das weiss er durch den cast auf den Typen.
    Eine Bytefummelei ist hier nicht nur nicht portierbar, sondern
    auch gefährlich.

    @showme: in C gibt es (noch) kein new 😉

    Edit by c.rackwitz: ich wuerde gerne sehen, dass du [cpp] Tags benutzt.



  • nemeses schrieb:

    Der Compiler weiss schon, das mit p_coords++ eine Erhöhung um
    32bit gemeint ist. Das weiss er durch den cast auf den Typen.
    Eine Bytefummelei ist hier nicht nur nicht portierbar, sondern
    auch gefährlich.

    Wo siehst du in meinem knappen Code-Fragment eine Byte-Fummelei? calloc() ist afaik genauso "sicher" wie malloc() und casten mußt du den zurückkommenden Pointer in jedem Fall.



  • lass dich von nemeses nicht irre machen. der postet ueberall lange codes ohne [cpp] tags und schrammt oft knapp am thema vorbei.



  • Hi,

    wie kann ich denn sicherstellen, dass der Speicher auch tatsächlich allokiert wurde?
    Muss dazu der Pointer *p_coords ungleich NULL sein?

    // Speicher allokieren. Ergebniss ist ein Array von SCoords 
    sCoords *p_coords = (sCoords*) malloc (sizeof (sCoords)*cnt);
    

    Diese Anweisung erstellt alloiert im Speicher ein Feld der Größe cnt*sizeof(sCoords). Der Zugriff erfolgt über den Pointer *p_coords. Was drückt (sCoords*) vor malloc aus?

    ----------------------------------------------------------------
    Könnt Ihr mir eine Quelle nennen, wo ich nachlesen kann über

    1. das Aufspannen eines zweidimensionales Feldes,
    2. die Verwendung des Synatax **. Ich kenne die rudimentäre Anwendung von Pointer, wie z.B.: int *nPtr.
    3. die Anweisung typedef.

    Vielen Dank.

    Gruß,

    W2K2005



  • malloc()

    2d felder koennen verschieden beschaffen sein. willst du eins mit malloc() aufziehen oder als automatische und konstant-grosse variable auf dem stack haben?

    doppelte sterne heisst "pointer auf pointer auf irgendwas". braucht man bei 2d feldern (listen von zeichenketten oder matrizen).

    mit typedef kannst du dir eigene typen basteln und sie mit einem einfachen namen ansprechen.

    du brauchst ein gutes buch oder tutorial, in dem diese grundlagen erklaert werden.



  • CStoll schrieb:

    calloc() ist afaik genauso "sicher" wie malloc() und casten mußt du den zurückkommenden Pointer in jedem Fall.

    Lese in einem anderen Forum immer wieder dass man die pointer die von malloc() calloc() zurückkommen auf keinen Fall casten soll. ( verstehe zwar nicht warum ).
    Wenn du

    #include <stdlib.h>
    

    einbindest brauchst du auf jeden Fall nicht casten.
    Kurt



  • in c muss man einen void* pointer nicht casten, das wird von selber gemacht.
    in c++ meckert der compiler aber.

    man sollte deswegen so wenig casten, weil jeder cast eine weitere stelle ist, die man aendern muss, wenn man sich umentscheidet.

    calloc() und malloc() sind gleich "sicher", wobei die frage nach "sicher" bloedsinn ist.
    calloc() initialisiert nur den speicher mit nullen, was malloc() nicht macht.



  • Hi,

    ich möchte dynamisch mit malloc ein 2D-Feld aufspannen.

    a_11 a_12 a_13 a_14 .... a1n
    ...
    ...
    a_m1 a_m2 .....          a_mn
    


  • das kannst wieder du auf verschiedene arten machen.

    einfach anzulegen, schwer in der benutzung:

    int xdim = 20, ydim = 10, *array = malloc(sizeof(*array) * xdim * ydim);
    /* zu benutzen mit array[x + y*xdim] */
    free(array);
    

    mit sizeof(*array) bekomme ich die groesse des zellentypen.

    schwer anzulegen, einfach in der benutzung:

    int i, xdim = 20, ydim = 10;
    int **array = malloc(sizeof(*array) * ydim);
    for (i = 0; i < ydim; ++i)
        array[i] = malloc(sizeof(**array) * xdim);
    /* zu benutzen mit array[y][x] */
    for (i = 0; i < ydim; ++i)
        free(array[i]);
    free(array);
    

    es gibt noch eine mischform, bei der du wie bei der ersten variante einen grossen block benutzt, jedoch auf die verschiedenen "zeilen" extra nochmal pointer anlegst, die du in einem weiteren array speicherst:

    int i, j, xdim = 20, ydim = 10;
    int *mem, **matrix;
    mem = malloc(sizeof(*mem) * xdim * ydim);
    matrix = malloc(sizeof(*matrix) * ydim);
    for (i = 0; i < ydim; ++i)
        matrix[i] = mem + i * xdim;
    /* zu benutzen mit matrix[y][x]; */
    free(matrix);
    free(mem);
    

    alle codes sind ungetestet, also wenns nicht funktioniert, bitte sagen.



  • Hi,

    ich glaube das Prinzip zu verstehen.

    int i, xdim = 20, ydim = 10; 
    int **array = malloc(sizeof(*array) * ydim); 
    for (i = 0; i < ydim; ++i) 
        array[i] = malloc(sizeof(**array) * xdim); 
    /* zu benutzen mit array[y][x] */ 
    for (i = 0; i < ydim; ++i) 
        free(array[i]); 
    free(array);
    

    Du legst also erst einen Vektor mit ydim Elementen an. Aber warum benutzt Du da gleich **array? Würde *array nicht auch funktionieren?

    Anschließend erzeugst Du dann von dem Zeilenvektor xdim Spalten. Das gefällt mir!

    Könntest Du vielleicht noch kurz erklären, was ein CAST ist? Ansonsten vielen Dank. War gut verständlich!



  • int **array
    

    ein array von int*-pointern.
    jeder int*-pointer zeigt auf eine zeile.

    ein int* wuerde nicht funktionieren, weil ich dann ja nur ein array von ints haette.

    ein cast ist, wenn man einen typen in einen anderen typen umwandelt und der compiler versucht, was sinnvolles aus den daten zu machen, die man castet.
    so z.b. kann man einen double nach int casten und man bekommt, was man erwartet. der compiler weiss eben, wie man zwischen zahlentypen ordentlich umwandelt.
    wenn man aber z.b. einen pointertyp in den anderen castet, passiert eigentlich nichts, weil immernoch an die selbe stelle gezeigt wird.
    man kann aber auch einen string zum int casten, was in den meisten faellen absolut schwachsinnig ist, weil nur muell rauskommt. man wuerde ja praktisch die ersten 4 zeichen des strings als die 4 bytes des ints verwenden. beispiel:

    char string[5] = "ABCD"; long int zahl = *(long int *)string;
    

    ich caste den string (zeiger auf char) zum zeiger auf int und dereferenziere dann.

    man kann auch sowas machen:

    char string[] = "Hallo Welt"; printf("adresse: %d\n", (int)string);
    

    ohne den cast nach int wuerde der compiler vielleicht meckern. so sagt man dem compiler, dass man wirklich aus dem pointer ne zahl machen will. die zahl ist hier dann eben die adresse des (ersten zeichens des) strings.



  • double **dataBag = (dataBag*) malloc(sizeof(*dataBag) * ydim);
    for (i = 0; i < ydim; ++i) {
       dataBag[i] = (double*) malloc(sizeof(*dataBag) * xdim); 
    }
    

    Ich habe gerade versucht mein Feld dataBag aufzuziehen - es klappt aber irgendwie nicht. Wäre für Tips dankbar.

    FEHLERMELDUNG:
    -----------------------------------------------------------------------------------------------------------
    Kompilierung läuft...
    main.cpp
    c:\AFG_05_1\main.cpp(98) : error C2059: Syntaxfehler : ')'
    Fehler beim Ausführen von cl.exe.

    AFG_05_1.exe - 1 Fehler, 0 Warnung(en)
    -----------------------------------------------------------------------------------------------------------
    P.S.: Für Visual C++ 6.0 ist der CAST anscheinend doch notwendig - wenn ich diesen weglasse, erhöhen sich meine Fehlermeldungen gleich deutlich....



  • da fehlt ein sternderl

    double **dataBag = (dataBag**) malloc(sizeof(*dataBag) * ydim);
    for (i = 0; i < ydim; ++i) {
       dataBag[i] = (double*) malloc(sizeof(*dataBag) * xdim);
    }
    

    Wennst als c++ compilierest ( .cpp ) dann musst du casten.
    Kurt



  • Das funktioniert leider immer noch nicht. Die Fehlermeldung ist unverändert.

    Kurt kannst Du mir einmal erklären - was da passiert. Wie kann ein sizeOf verwendet werden, wenn der Pointer dataBag noch gar nicht zuvor definiert wurde?



  • W2K2005 schrieb:

    Das funktioniert leider immer noch nicht. Die Fehlermeldung ist unverändert.

    Kurt kannst Du mir einmal erklären - was da passiert. Wie kann ein sizeOf verwendet werden, wenn der Pointer dataBag noch gar nicht zuvor definiert wurde?

    Sorry mein Fehler
    muss natürlich

    double **dataBag = (double**) malloc(sizeof(double *) * ydim);
    

    sein
    Kurt



  • Hallo Kurt:

    Super! Jetzt gehts.
    Hättest Du vielleicht noch einen Moment Zeit, um mir zu erklären, was hier passiert. Die Erklärung von c.crackwitz leuchtet mir noch nicht ganz ein.

    1 double **dataBag = (double**) malloc(sizeof(double *) * ydim);
    2 for (i = 0; i < ydim; ++i) 
    3     databag[i] = malloc(sizeof(**databag) * xdim); 
    4 }
    

    Zunächst wird ein Feld von double-Pointern (Dimension: ydim) allokiert.
    - Warum müssen diese von C++ gecastet werden? Crackwitz hat mir geschrieben, dass dies ein schlechter Stil ist.
    - Warum werden in Zeile 1 Pointer allokiert und nicht konventionelle Variablen?
    - **dataBag ist dann ein Pointer auf einen Pointer. Richtig?



  • W2K2005 schrieb:

    - Warum werden in Zeile 1 Pointer allokiert und nicht konventionelle Variablen?

    Weil hinter jedem Element von dataBag ein eigenes SubArray angelegt werden soll - d.h. die Elemente sind Pointer (und werden in Zeile 3 mit Werten gefüllt).

    - **dataBag ist dann ein Pointer auf einen Pointer. Richtig?

    Korrekt.



  • CStoll schrieb:

    - **dataBag ist dann ein Pointer auf einen Pointer. Richtig?

    Korrekt.

    Kommt jetz drauf an welches in

    sizeof(**databag)
    

    ists ein double 😉
    Kurt



  • CStoll schrieb:

    @showme: in C gibt es (noch) kein new 😉

    besser ist das. die heapverwaltung ist eine library und hat in der sprache nix verloren.



  • Hi,

    kannn mir bitte noch einmal jemand helfen. Ich bekomme diese 2D-Feld aus double-Zahlen nicht aufgespannt.

    double **dataBag = (double**) malloc(sizeof(double*) * ydim);
        for (i = 0; i < ydim; ++i) {
    	dataBag[i] = (double*) malloc(sizeof(double) * xdim);
        }
    

    Vielen Dank,

    W2K2005


Anmelden zum Antworten