2010-01-24 28 views
8

Chcę przydzielić macierz.Przydziel macierz w C

jest to jedyna opcja:

int** mat = (int**)malloc(rows * sizeof(int*)) 

for (int index=0;index<row;++index) 
{ 
    mat[index] = (int*)malloc(col * sizeof(int)); 
} 
+1

[Nie wyrzucaj wyniku malloc w C] (http: // stackoverflow.com/q/605845/995714) –

Odpowiedz

20

Cóż, nie dają nam pełną realizację. Zakładam, że miałeś na myśli.

int **mat = (int **)malloc(rows * sizeof(int*)); 
for(int i = 0; i < rows; i++) mat[i] = (int *)malloc(cols * sizeof(int)); 

Oto kolejna opcja:

int *mat = (int *)malloc(rows * cols * sizeof(int)); 

Następnie można symulować macierzy przy użyciu

int offset = i * cols + j; 
// now mat[offset] corresponds to m(i, j) 

dla row-major zamawiania i

int offset = i + rows * j; 
// not mat[offset] corresponds to m(i, j) 

dla kolumny-major zamawiania .

Jedna z tych dwóch opcji jest w rzeczywistości preferowanym sposobem postępowania z matrycą w C. Dzieje się tak, ponieważ teraz macierz będzie przechowywana w pamięci w sposób ciągły, a użytkownik skorzysta z locality of reference. Zasadniczo pamięć podręczna procesora będzie o wiele szczęśliwsza.

+1

jeśli twój kompilator obsługuje tablice o zmiennej długości lub jeśli 'cols' jest stałą czasu kompilacji, nie musisz nawet obliczać przesunięć; jeśli użyjesz 'int (* mat) [cols] = malloc (rows * sizeof * mat)', możesz uzyskać dostęp do elementów przez 'mat [i] [j]' i nadal korzystać z ciągłego bloku pamięci – Christoph

+1

Nawet ignorując wydajność , jedna alokacja jest również preferowana, ponieważ jest prostsza. Jest mniej rzeczy do deallocacji później i nie ma potrzeby radzenia sobie z częściowymi niepowodzeniami alokacji. – jamesdlin

+1

Czy nie byłoby to problemem, gdyby każdy malloc tworzył nieciągłą pamięć blokującą, czyniąc swoje adresy nie seriami? Na przykład, pierwszy malloc może zwrócić wskaźnik 0x635, a inne mallocs mogą zwrócić wskaźniki 0xA279, 0xB7DD, itd. Jeśli tak się stanie, proste obliczenia, takie jak podane powyżej, nie będą działać. –

2

Jak o właśnie:

int* mat = malloc(rows * columns * sizeof(int)); 
2

Możesz również użyć calloc, co dodatkowo zeruje inicjalizację macierzy dla ciebie. Podpis jest nieco inna:

int *mat = (int *)calloc(rows * cols, sizeof(int)); 
0

Ty może zwinąć go do jednego wywołania malloc, ale jeśli chcesz używać 2d styl tablicy, trzeba jeszcze do pętli.

int** matrix = (int*)malloc(rows * cols * sizeof(int) + rows * sizeof(int*)); 

for (int i = 0; i < rows; i++) { 
    matrix[i] = matrix + rows * sizeof(int*) + rows * cols * sizeof(int) * i; 
} 

Niewygodne, ale masz pomysł. W przeciwnym razie trzymałbym się tego, co sugeruje Jason.

+0

działa to tylko wtedy, gdy 'sizeof (int) == sizeof (int *)' - w przeciwnym razie przesunięcie będzie nieprawidłowe; w rzeczywistości może to być złe, nawet jeśli tak jest. – Christoph

+0

@ Christoph: Dobra rada, i łatwo można to obejść, ale jak zauważyłem w mojej odpowiedzi, jest to niesprawdzone. Naprawiono to teraz. –

-1

Dla n-wymiarowej tablicy można to zrobić:

int *matrix = malloc(D1 * D2 * .. * Dn * sizeof(int)); // Di = Size of dimension i 

uzyskać dostęp do komórki tablicy z typowym sposób można to zrobić:

int index = 0; 
int curmul = 1; 
int i; 
int indexes = {I1, I2, ..., In}; // Ii = Index in dimension i 

for(i = N-1; i >= 0; i--) { 
    index = index + indexes(i) * curmul; 
    curmul = curmul * Di; 
} 

(uwaga: nie zrobił testu, ale teraz Tłumaczenie z mojego kodu Matlab, ale w indeksie Matlab zaczyna się od 1, więc MOŻEMY popełniłem błąd (ale tak nie sądzę))

Miłej zabawy!

3

co można zrobić, to

int (*mat)[col]; 
mat=(int (*)[col])malloc(sizeof(*mat)*row); 

i następnie użyj tej nowej macierzy jako macie [i] [j]