Programowanie Proceduralne Unie, typdef, opeartory bitowe, operator przecinkowy Bożena Woźna-Szcześniak bwozna@gmail.com Jan Długosz University, Poland Wykład 11
Definicja Unia (ang. union) jest typem, który pozwala przechowywać różne rodzaje danych w tym samym obszarze pamięci (ale nie równocześnie). Dzięki uniom można na przykład utworzyć tablice jednostek o jednakowej długości, z których każda może przechowywać dane innego typu. Definicja unii jest analogiczna do definicji struktury, z wyjatkiem tego, że stosowane jest słowo kluczowe union. Kompilator przydziela tyle miejsca dla unii, aby mogła ona przechowywać największa ze zmiennych będac a częścia szablonu unii.
Przyklady union magazyn { int cyfra; double l_rzeczywista; char znak; ; Trzy unie typu magazyn /*unia typu magazyn */ union magazyn a; /*tablica 10 unii typu magazyn */ union magazyn tab[10]; /* wskaźnik do unii typu magazyn */ union magazyn *wu;
Przyklady Rozmiary unii #include <stdio.h> #include <stdlib.h> union magazyn { int cyfra; double l_rzeczywista; char znak; ; int main(void) { system("clear"); union magazyn a; printf("union magazyn a: %ld bajtow \n", sizeof(a)); union magazyn tab[10]; printf("union magazyn tab[10]: %ld bajtow \n", sizeof(tab)); union magazyn *wu; printf("union magazyn *wu: %ld bajtow \n",sizeof(wu)); return 0;
Przyklady Wykonanie union magazyn a: 8 bajtow union magazyn tab[10]: 80 bajtow union magazyn *wu: 8 bajtow
Inicjalizacja Unie moga być inicjalizowane, ale zasady sa nieco inne niż w przypadku struktur. Istnieja dwie możliwości: nadanie unii wartości innej unii tego samego typu lub inicjalizacja pierwszego składnika unii. Pamiętanie o tym, jaki rodzaj informacji znajduje się w unii w każdym momencie, jest obowiazkem programisty. Dostęp do składowych unii odbywa sie w taki sam sposób jak w strukturach, czyli za pomoca operatora przynależności (kropki,.) lub operatora przynależności pośredniej (strzałki, >).
Inicjalizacja #include <stdio.h> #include <stdlib.h> union magazyn { int cyfra; double l_rzeczywista; char znak; ; void druk(const union magazyn); int main(void) { system("clear"); union magazyn a; a.znak = A ; union magazyn b=a; union magazyn c={777; puts("a: "); druk(a); puts("b: "); druk(b); puts("c: "); druk(c); union magazyn d = { znak : D ; puts("d: "); druk(d); return 0; void druk(const union magazyn a) { printf("[%d -- %lf -- %c] \n", a.cyfra, a.l_rzeczywista, a.znak);
Inicjalizacja Wykonanie a: [-974036927 -- 0.000000 -- A] b: [-974036927 -- 0.000000 -- A] c: [777 -- 0.000000 -- ] d: [68 -- 0.000000 -- D]
Inicjalizacja unia.c #include <stdio.h> #include <stdlib.h> union Test { int i; float f; ; int main(void) { system("clear"); union Test t; printf("union Test {\n int i;\n float f;\n;\n\n"); printf("union Test t;\n\n"); printf("rozmiar unii t = %ld bajty\n\n", sizeof(t)); printf("po przypisaniu wartosci 1024.0 do pola f\n"); t.f = 1024.0; printf("pole i = %d\tpole f = %f\n\n", t.i, t.f); t.i = 1234567890; printf("po przypisaniu wartosci 1234567890 do pola i\n"); printf("pole i = %d\tpole f = %f\n\n", t.i, t.f); return 0;
Inicjalizacja Wykonanie union Test { int i; float f; ; union Test t; Rozmiar unii t = 4 bajty Po przypisaniu wartosci 1024.0 do pola f Pole i = 1149239296 Pole f = 1024.000000 Po przypisaniu wartosci 1234567890 do pola i Pole i = 1234567890 Pole f = 1228890.250000
Struktury a unie, enum #include <stdio.h> #include <stdlib.h> enum symboltype {INT, DOUBLE, CHAR; union Data {int i; double d; char c;; struct TableEntry { char *name; enum symboltype type; union Data data; ; int main(void) { struct TableEntry symtab[] = { {"ch", CHAR, {c : @, {"counter", INT, {i : 0, {"pi", DOUBLE, {d : 3.1417, {"x", 5, {8 ; int size = sizeof(symtab) / sizeof(struct TableEntry); for (int k = 0; k < size; ++k) { printf("%s\t\t", symtab[k].name); switch (symtab[k].type) { case CHAR: printf("%c\n", symtab[k].data.c); break; case DOUBLE: printf("%f\n", symtab[k].data.d); break; case INT: printf("%d\n", symtab[k].data.i); break; default: printf("nieznany typ (%d), element %d\n", symtab[k].type, k); break; return 0;
Struktury a unie, enum Wykonanie ch @ counter 0 pi 3.141700 x Nieznany typ (5), element 3
Przykład 1 #include <stdio.h> typedef float Cena; typedef Cena Notowania[10000]; typedef int T; typedef T tablica[20]; int main(void) { Notowania wig = {0,1,2; printf("%.2f\n", wig[0]); wig[0] = 1000; printf("%.2f\n", wig[0]); tablica a; for(int i=0; i<10;i++) a[i]=i; for(int i=0; i<10;i++) printf("%d\t",a[i]); printf("\n"); return 0;
Przykład 1 Wykonanie 0.00 1000.00 0 1 2 3 4 5 6 7 8 9
Przykład 2 #include <stdio.h> #include <stdlib.h> typedef enum {INT, DOUBLE, CHAR symboltype; typedef union {int i; double d; char c; Data; typedef struct {char *name; symboltype type; Data data; TableEntry; int main(void) { TableEntry symtab[] = { {"ch", CHAR, {c: @, {"counter", INT, {i : 0, {"pi", DOUBLE, {d : 3.1417, {"x", 5, {8 ; int size = sizeof(symtab) / sizeof(tableentry); for (int k = 0; k < size; ++k) { printf("%s\t\t", symtab[k].name); switch (symtab[k].type) { case CHAR: printf("%c\n", symtab[k].data.c); break; case DOUBLE: printf("%f\n", symtab[k].data.d); break; case INT: printf("%d\n", symtab[k].data.i); break; default: printf("nieznany typ (%d), element %d\n", symtab[k].type, k); break; return 0;
Przykład 2 Wykonanie ch @ counter 0 pi 3.141700 x Nieznany typ (5), element 3
Zbiór operatorów - alternatywa ^ - różnica symetryczna & - koniunkcja << - logiczne przesuniecie w lewo >> - logiczne przesuniecie w prawo ~ - negacja
Przykład #include <stdio.h> // oblicza ile bitow zajmuje liczba typu int int wordlength(); // pobierz n bitów x od pozycji p unsigned getbit(unsigned x, int p); // ustaw na 1 bit na pozycji p unsigned setbiton(unsigned x, int p); // ustaw na 0 bit na pozycji p unsigned setbitoff(unsigned x, int p); // zaneguj bity unsigned negatebit(unsigned x, int p); // pobierz n bitów x od pozycji p unsigned getbits(unsigned x, int p, int n);
Przykład int main(void) { unsigned x; printf("podaj nieujemn liczbe calkowita: "); scanf("%u", &x); int n = wordlength(); unsigned w = getbits(x, 1, 3); printf("\nbits(%u, 1, 3) = %u\n\n", x, w); for (int k = n - 1; k >= 0; --k) { printf("%d", getbit(x, k)); printf("\n\n"); return 0;
Przykład int wordlength(){ unsigned x = ~0; int n = 0; while (x!= 0) { x >>= 1; ++n; return n; // sizeof(unsigned) == size(int)
Przykład unsigned getbit(unsigned x, int p){ return (x >> p) & 0x1; unsigned setbiton(unsigned x, int p){ return x (1 << p); unsigned setbitoff(unsigned x, int p){ return x & ~(1 << p); unsigned negatebit(unsigned x, int p){ return x ^ (1 << p); unsigned getbits(unsigned x, int p, int n){ return (x >> p) & ~(~0 << n);
Przykład Wykonanie Podaj nieujemn liczbe calkowita: 8 bits(8, 1, 3) = 4 00000000000000000000000000001000
Przykład Wykonanie Podaj nieujemn liczbe calkowita: 255 bits(255, 1, 3) = 7 00000000000000000000000011111111
Przykład Wykonanie Podaj nieujemn liczbe calkowita: 45 bits(45, 1, 3) = 6 00000000000000000000000000101101
Wykonanie #include <stdio.h> int main(void) { double a; a = 3.14; printf("%lg\n", a); a = (a++, 14, 2*a); printf("%lf\n", a); return 0; Wynik 3.14 8.280000