Unia (programowanie)
Ten artykuł od 2022-04 wymaga zweryfikowania podanych informacji. |
Unia – typ danych w niektórych językach programowania, jak C, PHP (od wersji 8) lub asembler, grupujący wiele różnych sposobów interpretacji tego samego fragmentu pamięci. Odpowiednikiem unii w języku Pascal jest rekord z wariantami.
Charakterystyka unii
Unia jest podobna do struktury, jednak wszystkie pola zajmują ten sam obszar pamięci – rozmiar unii jest równy rozmiarowi największego jej składnika.
Przykładowo unia:
union nazwa_unii {
char tablica_znakowa[4];
int wartosc;
} u;
tworzy zmienną u, do której można mieć dostęp albo jako do liczby (u.wartosc), albo jako do tablicy znaków (u.tablica_znakowa).
Tego typu manewry są czasem przydatne w niskopoziomowym programowaniu. Użycie unii nie jest jednak zalecane w innych wypadkach, gdyż jest wybitnie wrażliwe na różnice w reprezentacji poszczególnych typów w pamięci. Ten sam program, używający unii może zupełnie inaczej działać w zależności od tego, czy liczby są zapisywane jako big endian, czy little endian i jaką mają długość w bajtach:
u.wartosc=0x44434241;
W u.tablica_znakowa znalazł się napis:
- 'ABCD' w przypadku procesora Intel, kompilator 32-bitowy
- 'AB' w przypadku procesora Intel, kompilator 16-bitowy dla DOS-u
- 'DCBA' w przypadku procesora Motorola,
Struktury jako pola unii
Elementami unii mogą być struktury, co czasem jest przydatne:
union liczba {
struct {
unsigned int a :8;
unsigned int b :8;
unsigned int c :8;
unsigned int d :8;
} rozbicie_na_bajty;
struct {
unsigned int a :16;
unsigned int b :16;
} rozbicie_na_slowa;
unsigned int liczba;
};
Unie anonimowe
C++ dopuszcza tzw. unie anonimowe w których nie ma ani nazwy unii, ani nazwy zmiennej:
union {
int liczba;
char znak;
};
Do pól takiej unii można dostawać się bezpośrednio używając ich nazw (np. liczba lub znak z przykładu powyżej). Czasem ten mechanizm jest stosowany przy umieszczaniu unii anonimowej jako pola struktury.
Porównanie z innymi rozwiązaniami
W różnych językach programowania stosuje się albo unie, albo inne, analogiczne rozwiązania. Metody, które można porównywać z uniami to:
- rekordy z wariantami
- atrybuty rozmieszczenia w pamięci od wskazanego przez programistę adresu,
- typ wariantowy.
Rekord z wariantami
Rekord z wariantami, w którym występują wyłącznie pola dla jednego wariantu, różni się od unii wyłącznie występowaniem pola znacznikowego (anonimowego bądź jawnego), które określa jaką aktualną postać ma rekord, tzn. która wartość (jakiego typu) jest aktualna.
Atrybuty rozmieszczenia
Również atrybuty, definiowane we frazach konkretnej deklaracji, określające położenie zmiennej w pamięci, umożliwiają uproszczoną i luźną implementację mechanizmów oferowanych przez unię. W tym przypadku działanie jest identyczne z unią, jednak kodzie źródłowym nie jest widoczne powiązanie poszczególnych "pól" (w tym przypadku niezależnych zmiennych, rozmieszczonych od tego samego adresu pamięci – zmiennych nakładanych). W działaniu tak rozumianych "pól" nie jest oczywiście wymagane, w przeciwieństwie do unii, stosowanie selekcji. Przykładem takiej implementacji jest dyrektywa absolute adres
dostępna w Turbo Pascalu. W tym przypadku adres
może mieć postać adresu bezwzględnego, w postaci liczbowej, ale można się również posłużyć identyfikatorem uprzednio zdefiniowanej zmiennej, co w pewnym stopniu ukazuje powiązania między zmiennymi. Można też uzyskać efekt niedostępny w uniach, tzn. dodać przesunięcie do adresu zmiennej na którą nakładamy inną zmienną. Nałożenie może więc dotyczyć dowolnej części pewnej zmiennej, a nie tylko jej początku.
var s:string[5]; {łańcuch}
len:byte absolute s; {długość łańcucha}
last:char absolute s[5]; {ostatni znak łańcucha}
Typ wariantowy
Również typ wariantowy ma pewne cechy analogiczne do unii. Jednak w tym przypadku różnice są istotne. Mianowicie w typie wariantowym, w przeciwieństwie do unii, cała implementacja jest ukryta przed programistą. W przypadku unii zaś programista jest zmuszony do implementowania operacji na uniach. Ponadto typ wariantowy nie narzuca ograniczeń na typ wartości, które może przyjmować zmienna wariantowa, natomiast w przypadku unii, wartości muszą być zgodne z typem jednego z pól unii. Przykładowym językiem programowania z typem wariantowym jest Visual Basic.