Przydzielone Array
Z przydzielonej tablicy To dosyć proste do naśladowania.
Zadeklaruj swój zestaw wskaźników. Każdy element tej tablicy punktów do struct Test
:
struct Test *array[50];
Następnie przydzielić i przypisać wskaźniki do struktur jednak chcesz. Za pomocą pętli byłaby prosta:
array[n] = malloc(sizeof(struct Test));
Następnie zadeklarować wskaźnik do tej tablicy:
// an explicit pointer to an array
struct Test *(*p)[] = &array; // of pointers to structs
Pozwala to używać (*p)[n]->data
; aby odwołać się do n-tego członka.
Nie martw się, jeśli ten problem jest mylący. To chyba najtrudniejszy aspekt C.
Dynamiczny Linear Array
Jeśli chcesz po prostu przeznaczyć bloku kodowanym (w praktyce tablicę kodowanym, nie wskaźniki do kodowanym) i posiada wskaźnik do bloku, ty można to zrobić łatwiej:
struct Test *p = malloc(100 * sizeof(struct Test)); // allocates 100 linear
// structs
następnie można wskazać tego wskaźnika:
struct Test **pp = &p
Nie masz już tablic wskaźników do struktur, ale to znacznie upraszcza całą sprawę.
Dynamiczne Array dynamicznie przydzielane elemencie
Najbardziej elastyczne, ale nie często potrzebne. Jest bardzo podobny do pierwszego przykładu, ale wymaga dodatkowej alokacji. Napisałem kompletny program, aby zademonstrować to, co powinno się dobrze skompilować.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Test {
int data;
};
int main(int argc, char **argv)
{
srand(time(NULL));
// allocate 100 pointers, effectively an array
struct Test **t_array = malloc(100 * sizeof(struct Test *));
// allocate 100 structs and have the array point to them
for (int i = 0; i < 100; i++) {
t_array[i] = malloc(sizeof(struct Test));
}
// lets fill each Test.data with a random number!
for (int i = 0; i < 100; i++) {
t_array[i]->data = rand() % 100;
}
// now define a pointer to the array
struct Test ***p = &t_array;
printf("p points to an array of pointers.\n"
"The third element of the array points to a structure,\n"
"and the data member of that structure is: %d\n", (*p)[2]->data);
return 0;
}
wyjściowa:
> p points to an array of pointers.
> The third element of the array points to a structure,
> and the data member of that structure is: 49
lub cały zestaw:
for (int i = 0; i < 100; i++) {
if (i % 10 == 0)
printf("\n");
printf("%3d ", (*p)[i]->data);
}
35 66 40 24 32 27 39 64 65 26
32 30 72 84 85 95 14 25 11 40
30 16 47 21 80 57 25 34 47 19
56 82 38 96 6 22 76 97 87 93
75 19 24 47 55 9 43 69 86 6
61 17 23 8 38 55 65 16 90 12
87 46 46 25 42 4 48 70 53 35
64 29 6 40 76 13 1 71 82 88
78 44 57 53 4 47 8 70 63 98
34 51 44 33 28 39 37 76 9 91
Dynamiczny wskaźnik tablicy Single-Dynamic Przydzielone elemencie
Ten ostatni przykład jest raczej specyficzny. Jest to dynamiczna tablica wskaźników, jak widzieliśmy w poprzednich przykładach, ale w przeciwieństwie do nich elementy są alokowane w pojedynczym przydziale pojedynczej. Ma to swoje zastosowania, najbardziej godne uwagi przy sortowaniu danych w różnych konfiguracjach, pozostawiając niezmienioną oryginalną alokację.
Zaczynamy przeznaczając pojedynczy blok elementów jak my w najbardziej podstawowym alokacji pojedynczego bloku:
struct Test *arr = malloc(N*sizeof(*arr));
Teraz możemy przeznaczyć oddzielny blok wskaźników:
struct Test **ptrs = malloc(N*sizeof(*ptrs));
Następnie zapełniamy każdy slot na naszej liście wskaźnikowej adresem jednej z naszych oryginalnych tablic. Ponieważ wskaźnik arytmetyka pozwala nam przenieść się z elementem adresu elementu, to jest prosta:
for (int i=0;i<N;++i)
ptrs[i] = arr+i;
W tym momencie po odnoszą się do tego samego elementu pola
arr[1].data = 1;
ptrs[1]->data = 1;
i po przeglądu wyżej , Mam nadzieję, że jest jasne, , dlaczego.
Kiedy skończymy z tablicy wskaźnik i oryginalnej tablicy bloku są uwolnione jako:
free(ptrs);
free(arr);
Uwaga: Nie uwolnić każdy element w tablicy ptrs[]
indywidualnie. To nie jest sposób ich alokacji. Zostały one przydzielone jako pojedynczy blok (wskazany przez arr
) i tak powinny zostać uwolnione.
Dlaczego więc ktoś chciałby to zrobić? Kilka powodów.
Po pierwsze radykalnie zmniejsza liczbę wywołań przydziału pamięci. Zamiast tego N+1
(jeden dla tablicy wskaźnikowej, N dla poszczególnych struktur) masz teraz tylko dwa: jeden dla bloku tablicowego i jeden dla tablicy wskaźnikowej. Przydzielanie pamięci jest jedną z najdroższych operacji, które program może zażądać, a gdy jest to możliwe, pożądane jest ich minimalizowanie (uwaga: plik IO jest inny, fyi).
Kolejny powód: wiele reprezentacji tej samej podstawowej macierzy danych. Załóżmy, że chcesz posortować dane zarówno rosnąco, jak i malejąco i posortować obie reprezentacje w tym samym czasie: w tym samym czasie:. Można powielić macierz danych, ale wymagałoby to dużej ilości kopiowania i spożywania znacznej ilości pamięci. Zamiast tego po prostu przydziel dodatkową tablicę wskaźnika i wypełnij ją adresami z tablicy podstawowej, a następnie posortuj tablicę wskaźnika. Ma to szczególne znaczenie, gdy sortowane dane są duże (być może kilobajtów lub nawet większe, na element). Oryginalne elementy pozostają w swoich pierwotnych lokalizacjach w macierzy podstawowej, ale teraz masz bardzo wydajny mechanizm, w którym możesz je sortować bez konieczności faktycznego przeniesienia ich. Sortujesz tablicę wskaźników do pozycji; przedmioty w ogóle się nie poruszają.
Zdaję sobie sprawę, że jest to bardzo trudne do przyjęcia, ale użycie wskaźnika ma kluczowe znaczenie dla zrozumienia wielu potężnych rzeczy, które możesz zrobić w języku C, więc uderz w książki i odśwież swoją pamięć. Wróci.
zobacz http://stackoverflow.com/questions/11421884/memory-allocation-for-array-of-structure-pointers –
Czy chcesz faktycznego zestawu wskaźników do struktur? Jak w zadeklarowanej tablicy, w której alokujesz każdy element za pomocą struktury? – teppic
Cóż, chcę wskaźnik do tablicy, w której mogę wykonać to, co powiedziałeś. – DillPixel