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));
}
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));
}
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.
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
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
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ć. –
Jak o właśnie:
int* mat = malloc(rows * columns * sizeof(int));
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));
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.
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
@ Christoph: Dobra rada, i łatwo można to obejść, ale jak zauważyłem w mojej odpowiedzi, jest to niesprawdzone. Naprawiono to teraz. –
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!
innych odpowiedzi już objęte nich, ale dla kompletności comp.lang.c FAQ ma odpowiedniego wpisu:
http://c-faq.com jest niezwykłym źródłem takich rzeczy, jak hacki C (dla C++ http://www.parashift.com/c++-faq/) – 42n4
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]
[Nie wyrzucaj wyniku malloc w C] (http: // stackoverflow.com/q/605845/995714) –