kostenloser Webspace werbefrei: lima-city


Grosse Array vorinitialisieren?

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    klasset

    klasset hat kostenlosen Webspace.

    Hello World! =)

    Ich steh wieder einmal mit einem riesen Array vor der Tür in C++.
    Der Speicher für das boolean Array wird dynamisch reserviert und die grösse ist vom Input abhängig.
    Da mein nach folgender Algorithmus erwartet, dass alle Einträge mit "false" markiert sind, muss ich das vorinitialisieren. Doch wie mach ich das ohne zwei for-schleifen zu verwenden.
    Oh habe ich erwähnt es ist ein zweidimensionales Array.

    bool** bNumb;
    
     // Vereinfachen à la C-Style?
        bNumb = new bool*[iN+1];
        for(int i=0; i < iN+1; i++)
        {
            bNumb[i] = new bool[iHSum+1];
            for(int j=0; j < iHSum; j++)
            {
                bNumb[i][j] = false;
            }
        }


    überigens "vectors" sind zu langsam.

    Danke für jegliche Hilfe!

    mfg KlasseT
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Also der Code lässt sich schonmal wesentlich schneller ausführen indem du Zeiger verwendest und (bei der Initialisierung) nicht zweidimensional arbeitest:
    bnum = new bool*[iN+1];
    bool **i_ptr,*j_ptr;
    i_ptr = bnum;
    for(int i =0; i < iN+1; i++)
    {
        j_ptr = new bool[iHSum+1];
        *i_ptr++ = j_ptr;
        for(int j=0; j < iHSum+1; j++)
        {
            *j_ptr++ = false;
        }
    }


    Zur Erklärung:
    Mit dem Zeiger i_ptr durchlaufen wir den Array bnum von vorne nach hinten.
    Dabei dereferenzieren wir immer mit *i_ptr die aktuelle Position.
    *i_ptr++ dereferenziert und geht gleichzeitig einen Schritt weiter.
    In der inneren Schleife passiert dasselbe nochmal mit j_ptr.
    Der Grund hier mit Zeigern zu arbeiten ist folgender:
    Für jeden Arrayzugriff mit [ i ] muss folgende Formel berechnet werden:
    i * size + offset
    Dabei ist i der index size die größe des gespeicherten Datentyps und offset der Anfang des Arrays.
    Wie du siehst eine Multiplikation und eine addition pro [ i ].
    Bei doppelten [][] kommt das also auch gleich zweimal.
    Wenn du hingegen mit Zeigern arbeitest, dann muss der Zeiger nur eins weitergeschoben werden.
    Das funktioniert Natürlich mit altePosition + size. Wie du siehst nur eine Addition, die folglich wesentlich
    schneller geht.

    Zum Schluss noch die Anmerkung, dass du auch selbst diese Berechnungen machen kannst und
    dafür den Array eindimensional behandelst. Damit sparst du dann auch die zweite Schleife ein.

  4. Warum Schleifen ?

    void * memchr ( const void *, int, size_t );

    Parameters
    ptr
    Pointer to the block of memory where the search is performed.
    value
    Value to be located. The value is passed as an int, but the function performs a byte per byte search using the unsigned char conversion of this value.
    num
    Number of bytes to be analyzed.

    Vorsicht bool variablen kannst du zwar nur 0 und 1 zuweisen belegen aber oft den Speicher von einem int.

    dann belegt ein unsigned char array kleiner auf einem 32bit Rechner nur ein viertel Platz.
  5. Ich glaube mein Vorposter hat da was verwechselt. Er meint sicherlich die Funktion memset.

    Der Vorteil vom memset() ist natürlich, dass die meisten Prozessoren einen eigenen sehr schnellen Maschinenbefehl haben, um diese Operation auszuführen.
  6. Ich würde das Array vermutlich nicht mit new sondern mit malloc erzeugen und mit free anstatt delete freigeben. Die Funktion calloc ist entspricht der malloc Funktion bis auf den Vorteil, dass alle Werte direkt auf 0 gesetzt werden.

    Dokumentation von calloc: http://msdn.microsoft.com/en-us/library/3f8w183e(VS.71).aspx

  7. Autor dieses Themas

    klasset

    klasset hat kostenlosen Webspace.

    wibald schrieb:

    Warum Schleifen ?

    void * memchr ( const void *, int, size_t );


    bladehunter schrieb: Ich glaube mein Vorposter hat da was verwechselt. Er meint sicherlich die Funktion memset..


    Genau das hab ich gesucht, ich wusste es gibt ne andere Methode! :-)
    Danke!

    Jetzt muss ich nur noch heraus finden, wie das am besten für ein zwei dimensionales array funktioniert...

    Vorsicht bool variablen kannst du zwar nur 0 und 1 zuweisen belegen aber oft den Speicher von einem int. dann belegt ein unsigned char array kleiner auf einem 32bit Rechner nur ein viertel Platz.

    Ja?! Ok, jedoch glaub ich dass die Geschwindigkeit dann wieder beim vergleich ob die Variable "true" oder "false" verloren geht...

    cpp0x schrieb: Ich würde das Array vermutlich nicht mit new sondern mit malloc erzeugen und mit free anstatt delete freigeben. Die Funktion calloc ist entspricht der malloc Funktion bis auf den Vorteil, dass alle Werte direkt auf 0 gesetzt werden.

    Dokumentation von calloc: http://msdn.microsoft.com/en-us/library/3f8w183e(VS.71).aspx


    Sprich einfach die C-Variante für die Speicher reservierung.
    Mit dem Vorteil der 0 initialisierung...

    Weiss nun jemand wie man ein 2D Array entweder mit memset() oder calloc() macht?

    mfg KlasseT
  8. klasset schrieb:
    wibald schrieb:

    Warum Schleifen ?

    void * memchr ( const void *, int, size_t );


    bladehunter schrieb: Ich glaube mein Vorposter hat da was verwechselt. Er meint sicherlich die Funktion memset..


    Genau das hab ich gesucht, ich wusste es gibt ne andere Methode! :-)
    Danke!

    Jetzt muss ich nur noch heraus finden, wie das am besten für ein zwei dimensionales array funktioniert...

    Vorsicht bool variablen kannst du zwar nur 0 und 1 zuweisen belegen aber oft den Speicher von einem int. dann belegt ein unsigned char array kleiner auf einem 32bit Rechner nur ein viertel Platz.

    Ja?! Ok, jedoch glaub ich dass die Geschwindigkeit dann wieder beim vergleich ob die Variable "true" oder "false" verloren geht...

    cpp0x schrieb: Ich würde das Array vermutlich nicht mit new sondern mit malloc erzeugen und mit free anstatt delete freigeben. Die Funktion calloc ist entspricht der malloc Funktion bis auf den Vorteil, dass alle Werte direkt auf 0 gesetzt werden.

    Dokumentation von calloc: http://msdn.microsoft.com/en-us/library/3f8w183e(VS.71).aspx


    Sprich einfach die C-Variante für die Speicher reservierung.
    Mit dem Vorteil der 0 initialisierung...

    Weiss nun jemand wie man ein 2D Array entweder mit memset() oder calloc() macht?

    mfg KlasseT


    für int wert[2][4];

    c code:

    int **wert = calloc(sizeof(int),2*4);

    ...


    free(wert);

    bitte korrigieren, falls das free nicht ausreichend ist.

    Beitrag zuletzt geändert: 24.5.2010 16:32:17 von cpp0x
  9. klasset schrieb:
    Sprich einfach die C-Variante für die Speicher reservierung.
    Mit dem Vorteil der 0 initialisierung...

    Weiss nun jemand wie man ein 2D Array entweder mit memset() oder calloc() macht?

    mfg KlasseT


    memset ist doch eine ganz andere Funktion als calloc/malloc. Erstere manipuliert einen existierenden Speicherblock und die alloc-Funktionen legen hingegen einen neuen Speicherblock an.

    Für ein 2-dimensionales Array hast du 2 Möglichkeiten: Entweder zu faltest die 2. Dimension in die erste hinein, so dass du nur ein 1-Dimensionales Array hast und mit 2 Variablen dieses Array verwaltest, oder du erzeugst ein Array aus Pointern, das auf Speicherbereiche zeigt, die dann die Werte in der 2. Dimension enthalten.

    Die erste Variante funktioniert bei einem 4*5 Array folgendermaßen: Du hast ein Array der Größe 20 und wenn du auf die Felder [3][2] zugreifen willst, dann entspricht dies dem Feld 5*3+2 in deinem eindimensionalem Array.

    Bei der Zweiter Variante legst du einfach ein Array mit Pointern an und gehst mit der For-Schleife über jedes Feld, um einen neuen Speicherblock mit calloc zu reservieren und die Speicheradresse dieses Blocks dann in dem aktuellem Feld zu speichern.
  10. Autor dieses Themas

    klasset

    klasset hat kostenlosen Webspace.

    cpp0x schrieb:

    für int wert[2][4];
    c code:
    int **wert = calloc(sizeof(int),2*4);
    ...
    free(wert);

    bitte korrigieren, falls das free nicht ausreichend ist.


    Naja das Ganze stimmt nicht... :-)
    Die Syntax ist:
    void * calloc(anzal Elemente, Element grösse);

    also
    int **wert = calloc(2*4,sizeof(int));

    und da int** kein void* ist, geht das auch nicht...

    Naja mit C++ Type-Casting kenn ich mich nicht aus, vielleicht würde es damit gehen, jedoch mit der C-Variante (bool**) erhält man keinen Fehler, jedoch funktioniert es auch nicht. (Segmentation Fault)

    Im Internet hab ich noch weitere Lösungen gefunden, welche dann auch wieder mit Schleifen arbeiten, was ich genau versuche zu verhinden...

    memset ist doch eine ganz andere Funktion als calloc/malloc.


    Stimmt! :-)

    Die erste Variante funktioniert bei einem 4*5 Array folgendermaßen: Du hast ein Array der Größe 20 und wenn du auf die Felder [3][2] zugreifen willst, dann entspricht dies dem Feld 5*3+2 in deinem eindimensionalem Array.


    Okay, das muss ich noch etwas genauer anschauen, jedoch hoffe ich, dass dies in Kombination mit calloc für ein eindimensionales Array, die Lösung ist.
  11. int **wert = (int**)calloc(2*4,sizeof(int)); *glaub*
  12. Autor dieses Themas

    klasset

    klasset hat kostenlosen Webspace.

    cpp0x schrieb:
    int **wert = (int**)calloc(2*4,sizeof(int)); *glaub*


    oh hab ich vergessen zu erwähnen, funktioniert auch nicht...
    Bzw wie gesagt ich bekomme kein Fehler, aber das Programm stürtzt (unter Windows) ab und auf Linux bekomm ich Segmentation fault...

    Oder ich hab es falsch gemacht. :-P
  13. Es gibt in C und C++ keine Möglichkeit für dynamische multidimensionale Arrays.

    Das geht nur statisch.

    Die beste Möglichkeit ist eine C++ Klasse die dir das alles kapselt.

    Aber auch da gibt es meines Wissens keine Möglichkeit den mehrdimensionale operator zu überladen.

    Aber mit get/set methoden dürfte das kein problem sein.

    Dann noch eine extra Init oder create methode verwenden weil Fehlerbehandlung und/oder exceptions in Konstruktoren
    zu viele Probleme machen.

    class My2DimArray
    {
    public:
    My2DimArray(void);
    ~My2DimArray(void);
    bool Init(unsigned int x, unsigned int y);
    bool SetValue(unsigned int x, unsigned int y, bool value);
    bool GetValue(unsigned int x, unsigned int y);
    };

    Du wolltest ja bool arrays .. aber selbstverständlich kannst du über Templates diese Klasse für beliebige Datentypen verwenden.




  14. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!