jeśli ta struktura ma być używana przez jakiś inny plik func.c, jak to zrobić?
Kiedy typ jest używany w pliku (np. Plik func.c), musi być widoczny. Najgorszym sposobem na zrobienie tego jest skopiowanie i wklejenie go do każdego pliku źródłowego tego potrzebnego.
Właściwym sposobem jest umieszczenie go w pliku nagłówkowym i dołączenie tego pliku nagłówkowego, gdy jest to potrzebne.
czy powinniśmy otworzyć nowy plik nagłówkowy i zadeklarować tam strukturę i dołączyć ten nagłówek do func.c?
Jest to rozwiązanie, które lubię bardziej, ponieważ sprawia, że kod jest wysoce modułowy. Zakodowałbym twoją strukturę jako:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
Funkcje wykorzystujące tę strukturę umieściłbym w tym samym nagłówku (funkcja, która jest „semantycznie” częścią jej „interfejsu”).
Zwykle mogłem nazwać plik po nazwie struktury i użyć tej nazwy ponownie, aby wybrać definicje ochrony nagłówka.
Jeśli chcesz zadeklarować funkcję za pomocą wskaźnika do struktury, nie będziesz potrzebować pełnej definicji struktury. Prosta deklaracja forward, taka jak:
struct a ;
Wystarczy, a to zmniejszy sprzężenie.
czy też możemy zdefiniować całkowitą strukturę w pliku nagłówkowym i zawrzeć ją zarówno w source.c, jak i func.c?
Jest to inny sposób, nieco łatwiejszy, ale mniej modułowy: niektóre kody wymagające do działania tylko Twojej struktury będą nadal musiały zawierać wszystkie typy.
W C ++ może to prowadzić do interesujących komplikacji, ale jest to poza tematem (brak tagu C ++), więc nie będę się rozpisywał.
następnie jak zadeklarować tę strukturę jako zewnętrzną w obu plikach. ?
Być może nie widzę sensu, ale Greg Hewgill ma bardzo dobrą odpowiedź w swoim poście Jak zadeklarować strukturę w nagłówku, która ma być używana przez wiele plików w c? .
powinniśmy więc wpisać to jak?
- Jeśli używasz C ++, nie rób tego.
- Jeśli używasz C, powinieneś.
Powodem jest to, że zarządzanie strukturą w C może być uciążliwe: musisz zadeklarować słowo kluczowe struct wszędzie, gdzie jest używane:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
Podczas gdy typedef pozwoli ci napisać go bez słowa kluczowego struct.
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
Jest to ważne, nadal zachować nazwę struktury. Pisanie:
typedef struct
{
/* etc. */
} MyStruct ;
po prostu utworzy anonimową strukturę z nazwą wpisaną w typoszeregu i nie będziesz w stanie jej zadeklarować. Dlatego zachowaj następujący format:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
W ten sposób będziesz mógł używać MyStruct wszędzie tam, gdzie chcesz uniknąć dodawania słowa kluczowego struct i nadal używać MyStructTag, gdy typedef nie zadziała (tj. Deklaracja do przodu)
Edytować:
Poprawiono błędne założenie dotyczące deklaracji struktury C99, jak słusznie zauważył Jonathan Leffler .
Edycja 2018-06-01:
Craig Barnes przypomina nam w swoim komentarzu, że nie trzeba zachowywać oddzielnych nazw dla nazwy struktury „tag” i jej nazwy „typedef”, tak jak to zrobiłem powyżej dla przejrzystości.
Rzeczywiście, powyższy kod można by napisać jako:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, to właśnie robi C ++ z prostszą deklaracją struktury, za kulisami, aby zachować zgodność z C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Wracając do C, widziałem oba zastosowania (oddzielne nazwy i te same nazwy) i żadna z nich nie ma wad, o których wiem, więc użycie tej samej nazwy ułatwia czytanie, jeśli nie używasz oddzielnych „przestrzeni nazw” w C dla struktur i innych symboli .
struct b
, ale wtedy twoja strukturaa
deklaruje typ, który nie jest używany (prawdopodobnie powinieneś zdefiniować nazwę elementu, być możek
po wewnętrznym nawiasie zamykającym i przed średnikiem