Frage nach der Speicherbelegung...



  • Hallo Forum...
    Ich habe folgenden Quelltext(stark vereinfacht):

    #include <R.h>
    #include <Rinternals.h>
    
    typedef unsigned int BLOCK;
    const int BITS_PER_BLOCK = sizeof(BLOCK) * 8;
    
    // [...]
    
    void main(SEXP A) {	// SEXP ist in dem Fall ein Matrix Objekt aus R
    	int N, NB;
    	BLOCK *m;
    	N = INTEGER(getAttrib(A, R_DimSymbol))[0]; // speichert einfach die Spaltengröße der quadratischen Matrix A
    
    	NB = N / BITS_PER_BLOCK + 1;
    	m = (BLOCK *) R_alloc(sizeof(BLOCK), NB * N) // Beschreibung zur Funktion R_alloc folgt unten
    	BLOCK *pos = m;
    	BLOCK shift = 0;
    	BLOCK *rstart = pos;
    	for (int col = 0; col < N; col++) {
    		if (abs(INTEGER(A)[col * N ]) > 0) // Es wird geprüft ob das Element der Matrix A in Spalte col (, 0. Zeile) größer als 0 ist
    			shift |=
    			    (1 <<
    			     (col & (BITS_PER_BLOCK - 1)));
    			if ((col & (BITS_PER_BLOCK - 1)) ==
    		    BITS_PER_BLOCK - 1) {
    			(*pos++) = shift;
    			shift = 0;
    		}
    	}
    }
    

    Erstmal die Beschreibung zur Funktion R_alloc:

    Aus einer R Manual
    Use
    char* R_alloc(long n, int size)
    which allocates n units of size bytes each.

    Nun Kommen meine Fragen...

    typedef unsigned int BLOCK;
    const int BITS_PER_BLOCK = sizeof(BLOCK) * 8;
    

    BLOCK belegt also 4 Bytes (unsigned int eben, oder)?
    BITS_PER_BLOCK hingegen ist (wenn BLOCK 4 Bytes belegt) 4 * 8 = 32. Das bedeutet BITS_PER_BLOCK belegt 4 Bytes, wobei es den Wert 32 enthält. Stimmt das?

    NB = N / BITS_PER_BLOCK + 1;
    

    Ich glaube diese Rechnung wird ausgeführt, damit man mit NB angeben kann, wieviele Speicherplätze des types Int (BIT_PER_BYTE = 32 Bit)man braucht, um eine ganze Reihe aus der Matrix unterzubringen, wenn man jedes Element in 1 Bit schreibt. (Die Matrix A besteht nur aus 1 und 0, also werden da nur Bits entnommen).

    m = (BLOCK *) R_alloc(sizeof(BLOCK), NB * N)
    

    Laut obiger Beschreibung werden also 4 Einheiten von NB*N großen Speicherfeldern angelegt. So ganz verstehe ich diese Speicherweise noch nicht. Insgesamt werden also 4 * NB*N Bytes reserviert... Genug also um die N*N große Matrix unterzubringen, wenn man jedes Element in ein Bit schreibt?
    m zeigt ja dabei auf die 1. Speicheradresse des angelegten Speicherplatzes?

    shift |=
    			    (1 <<
    			     (col & (BITS_PER_BLOCK - 1)));
              		if ((col & (BITS_PER_BLOCK - 1)) ==
               		BITS_PER_BLOCK - 1) {
                		(*pos++) = shift;
                		shift = 0;
    

    Das passiert nur, wenn das gerade kontrollierte Element aus A = 1 (also > 0) ist. Im Prinzip werden damit die Bits der 0. Zeile aus A in shift hineinkopiert(nur in umgekehrter Reihenfolge). Dabei wird die 1 maximal bis zur Stelle 32 verschoben, sonst würde ja der Speicher in shift (4 Bytes - Größe von BLOCK) überschritten, oder?
    Weil ich noch nicht ganz so sicher in Zeigern bin, nur noch zur Kontrolle:
    Der Pointer pos zeigt ja auf die Speicheradresse des großen Feldes (wo m draufgezeigt hat), also schreibt dieser durch (*pos++) = shift; erst den Wert von shift in die ersten 4 Bytes und rutscht dann um seinen Variablentyp (BLOCK), also um 4 Bytes weiter, oder?

    Insgesamt wird ja aber die Reihenfolge der Zeile aus A durcheinandergebracht, oder? Angenommen die Bits sind jetzt Zahlen (die einfach nur 1 Bit belegen) und A hat die folgende Zeile:

    1 2 3 4 5 6 7 8 9 10 11 12

    Wenn ein Speicherblock jetzt mal nicht 32 Stellen, sondern nur 4 fast, dann legt das Programm die Zeile ja wie folgt im Speicher an:

    4 3 2 1 - 8 7 6 5 - 12 11 10 9

    Stimmt das so?


Anmelden zum Antworten