2012-02-15 19 views
8

Nie jestem ekspertem od niskopoziomowych, nieobiektowych języków programowania, a ja jestem w trakcie pisania kodu C dla projektu w pracy. Próbuję stworzyć przyzwoite abstrakcyjne typy danych do pracy, a Google Googling uświadomił mi, że ludzie używają strukturalnych ADT na dwa sposoby. Niektóre osoby definiują typ danych jako strukturę:Kiedy powinieneś napisać struct struct vs pointer do struct?

typedef struct adt { 
    //content here 
} adt; 

i udostępnić go światu w pliku nagłówkowym.

Inne określić typ danych jako wskaźnik do struct:

// In .c file: 
typedef struct adt_s { 
    //content here 
} adt_s, *adt; 


// In .h file: 
typedef struct adt_s *adt; 

Rozumiem, że takie podejście pozwala na typedef struct bez podania światem zewnętrznym żadnej wiedzy o tym, co znajduje się wewnątrz tej struktury, tak programistów może tylko użyć funkcji dostarczonych w tym samym pliku nagłówkowym, aby operować na tym typie danych.

Czy istnieją inne powody, by wybrać inne? Czy istnieje ogólna "reguła", kiedy definiujemy ADT jako struktury i kiedy definiujemy je jako wskaźniki do struktur?

Odpowiedz

6

można przekazać deklarowania struct bez typedef zbyt - jedyne różnice to:

  • czy interfejs wygląda czystsze z lub bez hasła struct
  • czy interfejs wygląda czystsze z lub bez wyraźnej wskazówki *

Np.

struct S1; 
typedef struct S2 S2; 
typedef struct S3_s *S3; 

void foo1(struct S1 *arg); 
void foo2(S2 *arg); 
void foo3(S3); 

Oczywiście odnosi się to tylko do struktur zadeklarowanych do przodu w nagłówku interfejsu.

Jeśli nie ukrywasz najpierw implementacji struktury, wybór między S1 i S2 jest kwestią preferencji (lub spójności). Nie użyłbym S3, chyba że jest to naprawdę nieprzezroczysty/ukryty typ.

Osobista preferencja to użycie S1 (jawne słowo kluczowe struct) dla dużych/złożonych agregatów i S2 dla małych struktur, które można traktować jak wartości i nie zawsze przekazywane przez wskaźnik. YMMV.

+0

Dla celów czytelności może lepiej napisać 'typedef struct S3_s * S3' zamiast' typedef struct S3_s * S3', nie? – Eregrith

+0

@Egrith: jeśli przejdziesz przez formalną semantykę języka, 'typedef struct S3_s * S3' mówi, że deklarator' * S3' ma typ 'struct S3_s' i class przechowywania' typedef', więc umieszczenie gwiazdki z identyfikatorem jest faktycznie idiomatyczne ; jednak umieszczenie gwiazdki z typem jest bardziej dostosowane do tego, ile osób (najwięcej?) myśli o deklaracjach; o ile jestem przekonany, obie wersje są w porządku, o ile jesteś konsekwentny ... – Christoph

+0

Właśnie wybrałem ten odstęp dla spójności z OP, ponieważ widzę korzyści w dowolny sposób. – Useless

1

Decyzja o ukryciu lub ukryciu leży całkowicie w gestii projektodawcy Twojej biblioteki. Jeśli chciałbyś zarezerwować sobie prawo do zmiany swojej woli w przyszłości, nie powinieneś narażać żadnego ze swoich członków na "świat". Jeśli dostarczasz struct jako środek do komunikowania się z twoją biblioteką (na przykład, struct reprezentujący punkt w 3D), to nie możesz ukryć swoich członków przed światem, ponieważ to by zniszczyło cel.

1

przeczytać Linus Torvalds post Rozdział 5: typedefs