2013-05-07 16 views
5

Uczę się wyściełania i pakowania struktury w C. Mam tę wątpliwość, ponieważ przeczytałem dopełnienie zależy od architektury, więc ma wpływ na komunikację między maszynami ?, tj. jeśli dane utworzone na jednym komputerze są odczytywane na innym komputerze. Jak uniknąć tego problemu w tym scenariuszu.Wykładanie struktury

Odpowiedz

2

#pragma pack jest obsługiwany przez większość kompilatorów, które znam. To może pozwolić programiście na określenie pożądanej metody wypełniania dla struktur.

http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx

http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html

http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions

+0

To prawda, ale bardzo myląca w kontekście komunikacji w sieci lub udostępniania plików na różnych platformach. –

+0

Tak, można zmienić dopełnienie konstrukcji. ** To może być niebezpieczne.** Niektóre interfejsy API wymagają odpowiedniego wyrównania danych. Zmiana wypełnienia może zrujnować to. – Anthony

+0

I zmiana dopełnienia struktury nie wystarczy, aby dane były interpretowane tak samo na różnych komputerach. Istnieje wiele innych zagadnień, takich jak reprezentacja liczb swobodnych/podwójnych, reprezentowane liczby całkowite ze znakiem, jaka jest kolejność bajtów w liczbach całkowitych, jaka jest wielkość typu danych ('char',' int', 'long',' long long'?), i stosy więcej. – Anthony

6

Tak, nie można wysyłać dane binarne o strukturze pomiędzy platformami i oczekiwać, że wyglądają tak samo po drugiej stronie.

Sposób, w jaki to rozwiązujesz, to stworzenie marshallera/demarshallera dla twojego konstruktu i przekazanie go w drodze z jednego systemu i po drodze do drugiego systemu. Pozwala to kompilatorowi zająć się buforowaniem w każdym systemie.

Każda ze stron wie, jak pobrać dane, tak jak to określiłeś, i wysłać je na lokalną platformę.

Platformy takie jak Java obsługują to za Ciebie, tworząc mechanizmy serializacji dla twoich zajęć. W języku C musisz to zrobić samodzielnie. Sposób, w jaki to robisz, zależy od tego, w jaki sposób chcesz wysłać swoje dane. Możesz serializować do binarnego, XML lub cokolwiek innego.

+0

[xdr] (http://linux.die.net/man/3/xdr) jest wart obejrzenia. – Anthony

+0

Jednym z takich marshallerów/demarshallerów jest pakiet msgpack: http://msgpack.org/ – Matt

0

Będzie to miało wpływ tylko wtedy, gdy kod skompilowany dla innej architektury używa innego schematu dopełnienia.

W celu złagodzenia problemów zalecam pakowanie struktur bez wypełnienia. Tam, gdzie wymagane jest wypełnienie, użyj uchwytów na place (np. char reserved[2]). Ponadto nie używaj bitfieldów !! Nie są przenośne.

Należy również pamiętać o innych problemach związanych z architekturą. W szczególności endianness i rozmiary typów danych. Jeśli potrzebujesz lepszej przenośności, możesz serializować i dekompilować strumień bajtów zamiast przesyłać go jako struct.

0

Możesz użyć #pragma pack (1) przed deklaracją struct i #pragma pack() przed wyłączeniem pakowania opartego na architekturze; rozwiąże to połowę problemu, ponieważ niektóre typy danych są oparte na architekturze, aby rozwiązać drugą połowę, zwykle używam określonego typu danych, takiego jak int_16 dla 16 bitów całkowitych, u_int_32 dla 32 bitów całkowitych i tak dalej.

Spójrz na http://freebsd.active-venture.com/FreeBSD-srctree/newsrc/netinet/ip_icmp.h.html; to obejmuje opis niektórych sieciowych pakietów danych niezależnych od architektury.

1

W języku C/C++ jako pakiet danych używane są struktury. Nie zapewnia on enkapsulacji danych ani funkcji ukrywania danych (przypadek C++ jest wyjątkiem ze względu na jego semantyczne podobieństwo do klas).

Ze względu na wymagania dotyczące dopasowania różnych typów danych każdy element struktury powinien być naturalnie wyrównany. Członkowie struktury przyznali kolejno rosnący porządek.