Tworzenie struktury bez podawania jej typu.

0

Zastanawia mnie tworzenie struktur w sposób przedstawiony w tym linku http://www.binarytides.com/programming-udp-sockets-c-linux/ konkretnie linijka 21.
Zazwyczaj ja tworzyłem je w sposób następujący:

sockaddr my_socket;

Czym różnią się te sposoby?

0

niczym. jest pewna roznica miedzy C a C++ w syntaxie, ale imo i tak wyjdzie na to samo.

1

W C i C++:

struct A; // deklaracja (zwana też czasami "deklaracją wyprzedzającą" albo "zapowiadającą", chociaż widziałem też użycie słowotworu "predeklaracja")
struct A { ... }; // definicja

Możemy sobie teraz zdefiniować zmienne:

struct A obj; // C i C++
A obj; // C++

W C - dla wygody - możesz sobie zrobić alias za pomocą typedef, żeby nie pisać ciągle tego struct:

struct A { ... };
typedef struct A A;
A obj; // OK!
struct A obj; // OK!

W C++ jest to zbędne, bo struct A już wprowadza nazwę A do przestrzeni nazw. ;)
Tego typedefa można sklecić razem z definicją typu:

typedef struct A { ... } A;
A obj; // OK!
struct A obj; // OK!

Można jeszcze krócej, używając anonimowej struktury, ale trzeba pamiętać, że pozbawimy się pewnych możliwości:

typedef struct { ... } A;
A obj; // OK!
struct A obj; // FAIL!

[edit: Powyższe zwykle nie jest mile widziane, ale jest smutną rzeczywistością w niejednym projekcie. Wiele "można", nie wszystko "powinno się". ;) ]

struct A; // deklaracja
void foo(struct A* p); // deklaracja będąca prototypem (w C deklaracja i prototyp to dwie różne sprawy, ale to sprawy techniczne i wykraczające poza ten temat)
typedef struct A { // definicja 
    int x;
} A;
void foo(A* p) { // definicja
    p->x = 42;
}

// ale nie da się napisać deklaracji anonimowej struktury nie będącej jednocześnie definicją
?????; // nie możemy zadeklarować "zapowiadająco"
void foo(?????* p);
typedef struct { // deklaracja będąca definicją
    int x;
} A;

Jeżeli piszemy w C++, ale jesteśmy zmuszeni pracować z taką anonimową strukturą z C (legacy...), którą chcielibyśmy zadeklarować "zapowiadająco" - możemy użyć pewnej... No, może "sztuczka" to za dużo powiedziane, ale jest to rozwiązanie, które może nie rzuca się od razu samo na myśl:

//legacy_stuff.h
typedef struct { ... } LegacyType;
//fancy.h
struct fancy_t {
    struct LegacyType; // co to za typ?
    void foo(LegacyType* p);
};
//fancy.cpp
#include "fancy.h"
extern "C" {
  #include "legacy_stuff.h"
}

struct fancy_t::LegacyType : public ::LegacyType { }; // aaa... ;]
//...

Nawet jeżeli mamy alias w C, czy też używamy C++, możemy potrzebować tego struct jeśli zasłonimy sobie nazwę:

typedef struct A { ... } A; // C
struct A { ... }; // C++

// C / C++
int A; // ...OK! A w tym zakresie odwołuje się teraz do zmiennej
A obj; // FAIL
struct A obj; // OK!
1

W C - dla wygody - możesz sobie zrobić alias za pomocą typedef, żeby ciągle nie pisać tego struct:

Albo nie robić, i pisać, i nie brnąć w te anonimowe struktury w połączeniu z typedefem.

Uważam że typedef struct to antywzorzec.

1

To ja jeszcze jedną ciekawostke dopiszę:
int foo (struct bar *d) { } // C++
Kiedy bar nie jest znane kompilatorowi, traktowane jest to jako deklaracja struktury bar. Często wykorzystywane przy współpracy z jakimś C-api.
http://melpon.org/wandbox/permlink/C5RfDshO2diKUn81

1 użytkowników online, w tym zalogowanych: 0, gości: 1