2013-07-18 12 views
6

Zaimplementowałem podstawową strukturę kolejki w C używając wskaźników void. Postępuje się, jak następuje:Implementacja kolejki C za pomocą void * - dobra lub zła praktyka?

  • inicjowania struktury - ustawić wielkość zmiennej typu mają być przechowywane w kolejce
  • push - przekazać wskaźnik zmiennej być przechowywane w kolejce, a następnie chwyta kopia dla siebie
  • przód - struktura zwraca pustkę * do elementu z przodu. Mogę po prostu chwycić wskaźnik lub memcpy(), aby mieć kopię lokalną.

Sama struktura wygląda następująco:

struct queue 
{ 
    void* start; //pointer to the beginning of queue 
    void* end;  //-||- to the end 
    size_t memsize; //size of allocated memory, in bytes 
    size_t varsize; //size of a single variable, in bytes 
    void* initial_pointer;  //position of the start pointer before pop() operations 
}; 

początek i koniec są po prostu nieważne wskaźniki wskazujące na jakimś miejscu w aktualnie przydzielonego bloku pamięci. Jeśli wciśnie elementy w kolejce, zwiększam wskaźnik końcowy o varsize. Jeśli pop(), po prostu zmniejszam wskaźnik końcowy również o varsize.

Nie sądzę, że powinienem opublikować kod funkcji tutaj, to ponad 100 linii.

Pytanie: jest uważane za dobrą lub złą praktykę? Dlaczego nie)?

Uwaga: zdaję sobie sprawę, że istnieje wiele innych opcji dla kolejki w C. Po prostu pytam o jakość tego.

EDIT: Implementacja jest dostępna tutaj: http: // 89.70.149.19 /stuff/queue.txt (usuń spacje)

+2

Użyj size_t dla rozmiarów pamięci –

+0

Myślę, że dobrze napisać ogólny kod używając 'void *' –

+0

@RanEldan Dziękuję, zrobię to. Poprawiono to tutaj. – szczurcio

Odpowiedz

8

Jest OK, aby użyć void * jeśli nie wiem, typ i rozmiar obiektów, które mają być przechowywane w kolejce (w rzeczywistości biblioteka standardowa C podąża za tym samym podejściem, zobacz funkcje memcpy() i dla niektórych przykładów). Jednak byłoby lepiej użyć size_t (lub ssize_t, jeśli potrzebujesz podpisanego typu danych) do określania rozmiaru elementów przechowywanych w kolejce.

+1

Ran Eldan wspomniał, że już, poprawiłem to. OK, dziękuję za twoją opinię. Uważam, że to intuicyjne, ale widziałem ludzi, którzy twierdzili, że jest to "brzydkie". – szczurcio

+2

@szczurcio Chodzi o to, że tak naprawdę nie możesz zrobić nic innego, jeśli wcześniej nie znasz typu. Jeśli tak, to nie używaj 'void *' w żaden sposób dla lepszego bezpieczeństwa typu. –

2

Naprawdę nie pokazujesz nam wystarczająco dużo, aby być pewnym swojej implementacji. void* dla elementów danych użytkownika jest w porządku, nie można zrobić wiele, poza tym C

Ale podejrzewam, że masz wewnętrzny typ elementu listy, który służy do zarządzania poszczególne przedmioty, coś

struct list_item { 
    struct list_item* next; 
    void* data; 
}; 

Jeśli tak jest i twoi start i end wskaźniki są skierowane do tych elementów, to ostatecznie powinno używać typ elementu w deklaracji struct queue:

struct queue 
{ 
    struct list_item* start; //pointer to the beginning of queue 
    struct list_item* end;  //-||- to the end 
    size_t memsize; //size of allocated memory, in bytes 
    size_t varsize; //size of a single variable, in bytes 
    struct list_item* initial_pointer;  //position of the start pointer before pop() operations 
}; 

Aby to działało, nie musisz nawet ujawniać użytkownikowi definicji struct list_item użytkownika struct queue.

+0

Nie jestem pewien, co masz na myśli. start i end to po prostu puste wskaźniki wskazujące na pewną lokalizację w ramach aktualnie przydzielonego bloku pamięci. Jeśli wciśnie elementy w kolejce, zwiększam wskaźnik końcowy za pomocą varsize. Jeśli pop(), po prostu zmniejszam wskaźnik końcowy również przez varsize. – szczurcio

+0

EDYCJA: Dodałem link do kodu w moim pytaniu. – szczurcio

+0

@szczurcio, to bardzo niekonwencjonalna implementacja kolejki, zwykle będzie to coś z dynamicznymi elementami, jak to opisuję tutaj. Powinieneś dodać opis, który masz w komentarzu do pytania, w celach informacyjnych. Skasowałbym wtedy tę odpowiedź, która nie służy ci zbytnio. –

Powiązane problemy