2012-09-11 78 views
2

我試圖將三個正方形的2d數組存儲到緩衝區中,所以我使用了一個連續的內存塊。如果數組大小是rxr,我的公式是:與malloc一起使用緩衝區

buffer = (double*) malloc((r + r + r) * sizeof(double *) + 
    (r*r + r*r + r*r) * sizeof(double)); 

    if(buffer == NULL) { 
    printf("out of memory\n"); 
    return 0; 
    } 

    for(i = 0, j = 0; i < r; i++) { 
    a[i] = &buffer[j]; 
    j+=r; 
    } 

    for(i = 0; i < r; i++) { 
    b[i] = &buffer[j]; 
    j+=r; 
    } 

    for(i = 0; i < r; i++) { 
    c[i] = &buffer[j]; 
    j+=r; 
    } 

    a = buffer[j]; 
    b = buffer[j + r]; 
    c = buffer[j + r + r]; 

正如你所看到的,我迷路了。 a,b,c被聲明爲雙指針(意味着指向數組數組),所以我希望每個指針都有一個大小爲r的數組,每個元素都指向它自己的大小爲r的單獨數組。任何想法...

回答

2

你正在malloc'ing雙打自己malloc'ing指針混淆自己。只需分配這樣的雙打:

double* all = (double*) malloc(3*r*r*sizeof(double)); 

那麼你的實際矩陣去哪裏?

double *p1 = all; 
double *p2 = &all[r*r]; 
double *p3 = &all[2*r*r]; 

一個錯誤,請檢查過:)但問題是,你不需要對malloc了兩個雙*和雙。

+0

我不知道這個問題的答案,但是對於malloc指向矩陣的指針也不是一種好的方式,因爲指針本身就是數組? (註釋在這裏編輯:不是你的代碼只是設置我的指針到每個數組的第一個元素?我想有一個指向行的指針數組,每個指針指向它自己的數組表示它的列。) –

+0

指針是不是數組,它們是指針。是的,指針和數組之間有密切的相關性,但是如果你只在32位機器上使用'malloc'指針來分配'sizeof(double *)',4個字節。數組的名稱可以用作指針,是的,但指向數組的第一個元素。 'p [0]'和'* p'是相同的,可以互換的。 – cdarke

2

所以,如果我理解正確的話,你要什麼有三個r X r陣列(abc),但希望他們三個連續存儲;基本上,後備存儲將是單個3 x r x r陣列。

如果大小r在編譯時知和你在C99或支持變長數組一個C11的實施工作,你可以這樣做以下:

size_t r = ...; 

double (*a)[r] = NULL; 
double (*b)[r] = NULL; 
double (*c)[r] = NULL; 

double (*backing_store)[r][r] = malloc(3 * sizeof *backing_store); 
if (!backing_store) 
{ 
    // panic and exit 
} 

a = backing_store[0]; 
b = backing_store[1]; 
c = backing_store[2]; 

你可以再使用ab,並c,好像他們是正規r X r陣列double

a[i][j] = ...; 
printf("%f\n", b[x][y]); 

當你完成,你只需要釋放backing_store

free(backing_store); 

爲什麼這項工作?

表達backing_store具有類型「指針rrdouble - 元素陣列的陣列 - 元素,由於表達backing_store[i]相當於*(backing_store + i),下標操作者隱含地取消引用指針,所以表達式的類型是」 rrdouble - 元素陣列」,每個的backing_store[0]backing_store[1],並backing_store[2]的 - 元素陣列是r X r陣列的double

請記住,在大多數情況下s,類型「N -element array of T」的表達式被隱含地轉換(「decays」)爲類型「指向T」的表達式,並且其值是數組中的第一個元素的地址。

因此,表述backing_store[0]從類型「rrdouble - 元素陣列的陣列 - 元素」轉換爲「指針rdouble - 元素陣列」,這恰好是的a的類型,和值是第一個子數組的地址(恰好與backing_store相同)。同樣,應用下標運算符會隱式地解除對指針的引用,因此a之後給出i th數組的第j個元素。

如果r在編譯時已知(即,它是一個常量表達式),那麼該過程是一樣的,只是你不必聲明變量r

#define R ... 

double (*a)[R] = NULL; 
double (*b)[R] = NULL; 
double (*c)[R] = NULL; 

double (*backing_store)[R][R] = malloc(3 * sizeof *backing_store); 
if (!backing_store) 
{ 
    // panic and exit 
} 

a = backing_store[0]; 
b = backing_store[1]; 
c = backing_store[2]; 

如果r而不是在編譯時已知您沒有可用的可變長度數組(使用C89或不支持VLA的C11編譯器),那麼它可能會變得更加混亂。在這裏,我們把backing_storedouble 1-d陣列和計算1-d標到每個子陣:

double *a = NULL; 
double *b = NULL; 
double *c = NULL; 

double *backing_store = malloc(3 * r * r * sizeof *backing_store); 
if (!backing_store) 
{ 
    // panic 
} 

a = backing_store; 
b = backing_store + r * r; 
c = backing_store + 2 * r * r;  

a[i*r+j] = ...; 
printf("%f\n", b[x*r+y]); 

同樣,你應該只需要釋放backing_store當你完成:

free(backing_store); 

不如使用二維下標漂亮,但它應該工作。

0

首先,二維數組通常更好地管理爲數組數組,而不是指向行的指針,除非有特別的理由使用指針。對於這一點,我們可以這樣做:

double (*Memory)[r][r] = malloc(3 * sizeof *Memory); 
    // Now Memory points to three r-by-r arrays of double. 
double (*a)[r] = Memory[0]; 
double (*b)[r] = Memory[1]; 
double (*c)[r] = Memory[2]; 

但是,如果你想使用指針行,那麼你應該爲指針,分別從要素分配空間分配空間。 (如果你不這樣做,那麼在C標準方面存在一些問題,特別是在填充和對齊方面。另外,你的代碼將buffer當作一個類型的數組, double [設定元件地址時]和有時需要指針double * [設定指針的地址時加倍])要使用的指針列,可以用這個分配:

double *(*PointerMemory)[r] = malloc(3 * sizeof *PointerMemory); 
    // PointerMemory points to three arrays of r elements of pointers to double. 
double (*ElementMemory)[r][r] = malloc(3 * sizeof *ElementMemory); 

然後,可以設置指針行:

// Set a to point to the first array of r elements of pointers to double. 
double *a[r] = PointerMemory[0]; 
// Initialize the elements of a to point to rows of the first r-by-r array of double. 
for (i = 0; i < r; ++i) 
    a[i] = ElementMemory[0][i]; 

// Set b for the second array of pointers and the second array of double. 
double *b[r] = PointerMemory[0]; 
for (i = 0; i < r; ++i) 
    b[i] = ElementMemory[1][i]; 

// Set c for the third arrays. 
double *c[r] = PointerMemory[0]; 
for (i = 0; i < r; ++i) 
    c[i] = ElementMemory[2][i];