C: gdzie Unia jest praktycznie używana?
Mam ze sobą przykład, w którym zagwarantowane jest wyrównanie typu, union max_align . Szukam jeszcze prostszego przykładu, w którym związek jest używany praktycznie, aby wyjaśnić mojego przyjaciela.
18 answers
Zwykle używam związków podczas parsowania tekstu. Używam czegoś takiego:
typedef enum DataType { INTEGER, FLOAT_POINT, STRING } DataType ;
typedef union DataValue
{
int v_int;
float v_float;
char* v_string;
}DataValue;
typedef struct DataNode
{
DataType type;
DataValue value;
}DataNode;
void myfunct()
{
long long temp;
DataNode inputData;
inputData.type= read_some_input(&temp);
switch(inputData.type)
{
case INTEGER: inputData.value.v_int = (int)temp; break;
case FLOAT_POINT: inputData.value.v_float = (float)temp; break;
case STRING: inputData.value.v_string = (char*)temp; break;
}
}
void printDataNode(DataNode* ptr)
{
printf("I am a ");
switch(ptr->type){
case INTEGER: printf("Integer with value %d", ptr->value.v_int); break;
case FLOAT_POINT: printf("Float with value %f", ptr->value.v_float); break;
case STRING: printf("String with value %s", ptr->value.v_string); break;
}
}
Jeśli chcesz zobaczyć, jak często używane są związki, sprawdź dowolny kod używając flex/Bizon . Na przykład patrz splint , zawiera mnóstwo związków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-20 13:11:20
Zazwyczaj używam związków, w których chcesz mieć różne poglądy na dane np. 32-bitowa wartość koloru, w której potrzebne są zarówno 32-bitowe wartości val,jak i Komponenty red,green, blue I alpha
struct rgba
{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
};
union
{
unsigned int val;
rgba components;
}colorval32;
NB można również osiągnąć to samo z bit-maskowanie i przesunięcie TJ
#define GETR(val) ((val&0xFF000000) >> 24)
Ale uważam, że podejście Unii jest bardziej eleganckie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:34:16
Aby uzyskać dostęp do rejestrów lub portów we/wy zarówno bajtowo, jak i bitowo poprzez mapowanie danego portu do pamięci, zobacz poniższy przykład:
typedef Union
{
unsigned int a;
struct {
unsigned bit0 : 1,
bit1 : 1,
bit2 : 1,
bit3 : 1,
bit4 : 1,
bit5 : 1,
bit6 : 1,
bit7 : 1,
bit8 : 1,
bit9 : 1,
bit10 : 1,
bit11 : 1,
bit12 : 1,
bit13 : 1,
bit14 : 1,
bit15 : 1
} bits;
} IOREG;
# define PORTA (*(IOREG *) 0x3B)
...
unsigned int i = PORTA.a;//read bytewise
int j = PORTA.bits.bit0;//read bitwise
...
PORTA.bits.bit0 = 1;//write operation
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:33:17
W świecie Windows, unions
są powszechnie używane do implementacji oznaczonych wariantów, które są (lub były, przed.NET?) jednym ze standardowych sposobów przekazywania danych pomiędzy obiektami COM.
Chodzi o to, że typ union
może zapewnić pojedynczy naturalny interfejs do przesyłania dowolnych danych między dwoma obiektami. Jakiś obiekt COM może przekazać Ci wariant (np. typ VARIANT
lub _variant_t
) które mogą zawierać albo double
, float
, int
, albo cokolwiek.
Jeśli masz aby poradzić sobie z obiektami COM w kodzie Windows C++, zobaczysz typy wariantów wszędzie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 13:41:37
struct cat_info
{
int legs;
int tailLen;
};
struct fish_info
{
bool hasSpikes;
};
union
{
fish_info fish;
cat_info cat;
} animal_data;
struct animal
{
char* name;
int animal_type;
animal_data data;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:17:24
Związki są przydatne, jeśli masz różne rodzaje wiadomości, w takim przypadku nie musisz znać na żadnym poziomie pośrednim dokładnego typu. Tylko nadawca i odbiorca muszą analizować aktualną wiadomość. Wszelkie inne poziomy tylko naprawdę muszą znać rozmiar i ewentualnie informacje o nadawcy i / lub odbiorcy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:58:34
SDL używa Unii do reprezentowania zdarzeń: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 18:25:00
Masz na myśli coś takiego ?
union {
long long a;
unsigned char b[sizeof(long long)];
} long_long_to_single_bytes;
Dodano :
Ostatnio użyłem tego na naszej maszynie AIX, aby przekształcić 64-bitowy identyfikator maszyny W tablicę bajtów.
std::string getHardwareUUID(void) {
#ifdef AIX
struct xutsname m; // aix specific struct to hold the 64bit machine id
unamex(&b); // aix specific call to get the 64bit machine id
long_long_to_single_bytes.a = m.longnid;
return convertToHexString(long_long_to_single_bytes.b, sizeof(long long));
#else // Windows or Linux or Solaris or ...
... get a 6byte ethernet MAC address somehow and put it into mac_buf
return convertToHexString(mac_buf, 6);
#endif
Oto kolejny przykład, w którym Unia może być przydatna.
(nie mój własny pomysł, znalazłem to na dokumencie omawiającym C++ optymalizacje)
Begin-quote
.... Związki mogą być również używane do oszczędzania miejsca, np.
Najpierw podejście pozaunijne:
void F3(bool useInt) {
if (y) {
int a[1000];
F1(a); // call a function which expects an array of int as parameter
}
else {
float b[1000];
F2(b); // call a function which expects an array of float as parameter
}
}
Tutaj można użyć tego samego obszaru pamięci dla a i b, ponieważ ich zakresy na żywo tak nie pokrywają się. Możesz zaoszczędzić dużo miejsca cpu-cache łącząc a i b W a "Unia": {]}
void F3(bool useInt) {
union {
int a[1000];
float b[1000];
};
if (y) {
F1(a); // call a function which expects an array of int as parameter
}
else {
F2(b); // call a function which expects an array of float as parameter
}
}
Używanie Unii nie jest oczywiście bezpieczną praktyką programowania, ponieważ nie Ostrzeżenie ze strony kompilatora, jeśli zastosowania a i b nakładają się na siebie. Należy używać tylko tej metody dla dużych obiektów, które zajmują dużo miejsca w pamięci podręcznej. ...
End-qoute
Używałem czasem związków w ten sposób
//Define type of structure
typedef enum { ANALOG, BOOLEAN, UNKNOWN } typeValue_t;
//Define the union
typedef struct {
typeValue_t typeValue;
/*On this structure you will access the correct type of
data according to its type*/
union {
float ParamAnalog;
char ParamBool;
};
} Value_t;
Następnie można zadeklarować tablice różnego rodzaju wartości, przechowując mniej lub bardziej efektywnie Dane i wykonać kilka operacji "polimorph", takich jak:
void printValue ( Value_t value ) {
switch (value.typeValue) {
case BOOL:
printf("Bolean: %c\n", value.ParamBool?'T':'F');
break;
case ANALOG:
printf("Analog: %f\n", value.ParamAnalog);
break;
case UNKNOWN:
printf("Error, value UNKNOWN\n");
break;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 23:59:12
- podczas odczytu danych serializowanych, które muszą być przypisane do określonych typów.
- zwracając wartości semantyczne z
lex
doyacc
. (yylval
) - przy implementacji typu polimorficznego, zwłaszcza takiego, który czyta DSL lub ogólny język
- podczas implementacji dyspozytora, który w szczególności wywołuje funkcje przeznaczone do przyjmowania różnych typów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 17:19:55
Ostatnio chyba widziałem jakiś związek używany w programowaniu wektorowym . programowanie wektorowe jest używane w technologii intel MMX , sprzęcie GPU, komórkowym silniku szerokopasmowym IBM i innych.
Wektor może odpowiadać rejestrowi 128-bitowemu. Jest bardzo powszechnie stosowany w architekturze SIMD. ponieważ sprzęt posiada 128-bitowe rejestry, w rejestrze/zmiennej można przechowywać 4 punkty zmiennoprzecinkowe o pojedynczej precyzji. łatwy sposób konstruowania, konwertowania, wyodrębniania poszczególnych elementami wektora jest użycie związku.
typedef union {
vector4f vec; // processor-specific built-in type
struct { // human-friendly access for transformations, etc
float x;
float y;
float z;
float w;
};
struct { // human-friendly access for color processing, lighting, etc
float r;
float g;
float b;
float a;
};
float arr[4]; // yet another convenience access
} Vector4f;
int main()
{
Vector4f position, normal, color;
// human-friendly access
position.x = 12.3f;
position.y = 2.f;
position.z = 3.f;
position.w = 1.f;
// computer friendly access
//some_processor_specific_operation(position.vec,normal.vec,color.vec);
return 0;
}
Jeśli podążasz ścieżką programowania wielordzeniowego PlayStation 3 lub programowania grafiki, jest duża szansa, że napotkasz więcej takich rzeczy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 18:45:15
Wiem, że jestem trochę spóźniony na imprezę, ale jako praktyczny przykład typ danych Variant
w Vbscripcie jest, jak sądzę, zaimplementowany jako Union
. Poniższy kod jest uproszczonym przykładem zaczerpniętym z artykułu znalezionego tutaj
struct tagVARIANT
{
union
{
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union
{
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
DATE date;
BSTR bstrVal;
SAFEARRAY *parray;
VARIANT *pvarVal;
};
};
};
Rzeczywista implementacja (jak stwierdza artykuł) znajduje się w oaidl.h c plik nagłówkowy.
Przykład:
Podczas używania różnych typów gniazd, ale chcesz, aby Typ comon się odnosił.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:00:47
Kolejny przykład więcej: aby zapisać robi odlewy.
typedef union {
long int_v;
float float_v;
} int_float;
void foo(float v) {
int_float i;
i.float_v = v;
printf("sign=%d exp=%d fraction=%d", (i.int_v>>31)&1, ((i.int_v>>22)&0xff)-128, i.int_v&((1<<22)-1));
}
Zamiast:
void foo(float v) {
long i = *((long*)&v);
printf("sign=%d exp=%d fraction=%d", (i>>31)&1, ((i>>22)&0xff)-128, i&((1<<22)-1));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:30:45
Dla wygody używam unions, aby pozwolić mi używać tej samej klasy do przechowywania wartości xyzw i RGBA
#ifndef VERTEX4DH
#define VERTEX4DH
struct Vertex4d{
union {
double x;
double r;
};
union {
double y;
double g;
};
union {
double z;
double b;
};
union {
double w;
double a;
};
Vertex4d(double x=0, double y=0,double z=0,double w=0) : x(x), y(y),z(z),w(w){}
};
#endif
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:40:26
Wiele przykładów związków można znaleźć w <X11/Xlib.h>
. Kilka innych znajduje się w niektórych stosach IP (na przykład w BSD <netinet/ip.h>
).
Z reguły implementacje protokołu używają konstrukcji Unii.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 09:26:53
Związki mogą być również użyteczne, gdy typują , co jest pożądane w kilku wybranych miejscach(np. niektóre techniki algorytmów porównywania zmiennoprzecinkowego ).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 19:59:13