Zu unterscheiden ist
union name { komponente_1, ..., komponente_n };
union { komponente_1, ..., komponente_n }
variable_1, ..., variable_m;
union name { komponente_1, ..., komponente_n }
variable_1, ..., variable_m;
union name variable_1, ..., variable_m;
union {
double matrix[1000][100];
long vektor[200000];
}
matrix und vektor belegen den gleichen Speicherplatz.
Der Speicherbereich kann jedoch jeweils anwendungsbezogen unter einem
anderen Namen angesprochen werden.
#include <stdio.h>
#include <string.h>
int main(void)
{
int i;
union record1 {
char c[8];
short s[4];
long l[2];
float f[2];
double d;
} r;
strcpy(r.c, "Error !");
printf("%s\n", r.c);
for(i=0;i<8;i++) printf("%d ", r.c[i]); printf("\n");
for(i=0;i<4;i++) printf("%d ", r.s[i]); printf("\n");
for(i=0;i<2;i++) printf("%ld ", r.l[i]); printf("\n");
for(i=0;i<2;i++) printf("%f ", r.f[i]); printf("\n");
printf("%lf\n", r.d);
return 0;
}
Es muß darauf hingewiesen werden, daß das Verhalten des
obigen Programms systemabhängig ist ! Gnu C unter Solaris 2.3 auf Sparc-Rechner Error ! 69 114 114 111 114 32 33 0 17778 29295 29216 8448 1165128303 1914708224 3879.152100 3171679751901599600558737457152.000000 356817125508989598744707072.000000 xlc unter AIX 3.2 auf RS/6000 69 114 114 111 114 32 33 0 17778 29295 29216 8448 1165128303 1914708224 3879.152100 3171679751901599600000000000000.000000 356817125508989600000000000.000000 Microsoft C 6.0 unter DOS Error ! 69 114 114 111 114 32 33 0 29253 28530 8306 33 1869771333 2170994 75033515763488890000000000000.000000 0.000000 0.000000 Gnu C unter DOS Error ! 69 114 114 111 114 32 33 0 29253 28530 8306 33 1869771333 2170994 75033515763488892360000000000.000000 0.000000 0.00000000000000
Beispiel für eine Union:
8- und 16-Bit-Register unter DOS
union _REGS { /* Union fuer Register des 80x86-Prozessors */
struct _WORDREGS x; /* 16-Bit-Register */
struct _BYTEREGS h; /* 8-Bit-Register */
};
struct _WORDREGS { /* 16-Bit-Register und Carry-Flag des 80x86 */
unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
unsigned int di;
unsigned int cflag;
};
struct _BYTEREGS { /* 8-Bit-Register des 80x86 */
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
Der Speicherplatzbedarf für eine Union wird durch den Speicherbedarf der "größten" Komponente bestimmt. Er ist jedoch nicht in jedem Fall mit diesem identisch. Hinzu kommen gegebenenfalls einige weitere Bytes, z.B. zur Ausrichtung auf eine Wortgrenze.
Beispiel:
#include <stdio.h>
int main(void)
{
union record1 {
char c[7]; /* 7 Byte + eventuell Ausrichtung auf 8 Byte */
int i[2]; /* 4 oder 8 Byte */
} r1;
union record2 {
char c[9]; /* 9 Byte + eventuell Ausrichtung auf 10 oder 12 Byte */
int i[2]; /* 4 oder 8 Byte */
} r2;
printf("%d %d\n", sizeof(r1), sizeof(r2));
return 0;
}
Testergebnisse:
Gnu C unter DOS, Gnu C unter Solaris 2.3 auf Sparc, xlc unter AIX 3.2 auf RS/6000 8 12 Borland C++ 4.52, 16-Bit, Microsoft C 6.0 7 9 Borland C++ 4.52, 32-Bit 8 9 Symantec C++ 8 10