część 14 struktury, unie, pola bitowe Jarosław Gramacki Instytut Informatyki i Elektroniki

Podobne dokumenty
METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Wstęp do programowania 1

Wykład Struktury i unie Deklarowanie i definiowanie struktur Dostęp do pól struktur Pola bitowe

część 6 biblioteka standardowa wejścia - wyjścia 1. sformatowane wejście - wyjście 2. rekordowe (binarne) wejście - wyjście

Język ANSI C. część 11. Jarosław Gramacki Instytut Informatyki i Elektroniki

Programowanie Proceduralne

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Wykład VI. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Wskaźniki w C. Anna Gogolińska

Podstawy programowania w języku C++

nowe operatory &. (kropka) * operator rzutowy ->, (przecinek) sizeof

Uzupełnienie dot. przekazywania argumentów

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

Tablice, funkcje - wprowadzenie

Podstawy programowania w języku C++

część 8 wskaźniki - podstawy Jarosław Gramacki Instytut Informatyki i Elektroniki Podstawowe pojęcia

Struktury czyli rekordy w C/C++

Język C zajęcia nr 11. Funkcje

Programowanie strukturalne i obiektowe

Funkcje zawarte w bibliotece < io.h >

Programowanie Proceduralne

Struktury. Przykład W8_1

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

W języku C każdy plik fizyczny jest ciągiem bajtów, z których każdy może być niezależnie odczytany. Borland 01234

Lab 9 Podstawy Programowania

Biblioteka standardowa - operacje wejścia/wyjścia

Struktury Struktura polami struct struct struct struct

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

x szereg(x)

Pliki. Informacje ogólne. Obsługa plików w języku C

Podział programu na moduły

۰ Elementem jednostkowym takiego pliku jest bajt. ۰ Format pliku binarnego: [bajty pliku][eof]

Funkcje zawarte w bibliotece < io.h >

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

KURS C/C++ WYKŁAD 7. struct Punkt { int x, y; int kolor; };

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Wstęp do Programowania, laboratorium 02

Podstawy Kompilatorów

Podstawy programowania. Wykład Co jeszcze... Przypomnienia, uzupełnienia. Krzysztof Banaś Podstawy programowania 1

KURS C/C++ WYKŁAD 6. Wskaźniki

Wstęp do programowania

Argumenty wywołania programu, operacje na plikach

Inżynieria Wytwarzania Systemów Wbudowanych

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 8. Karol Tarnowski A-1 p.

Języki programowania. Tablice struktur, pliki struktur. Część ósma. Autorzy Tomasz Xięski Roman Simiński

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 8. Karol Tarnowski A-1 p.

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

2 Przygotował: mgr inż. Maciej Lasota

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Wskaźniki. Informatyka

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Wskaźniki do funkcji. Wykład 11. Podstawy programowania ( język C ) Wskaźniki do funkcji (1) Wskaźniki do funkcji (2)

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Stałe, tablice dynamiczne i wielowymiarowe

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Operacje na plikach. Informatyka. Standardowe strumienie wejścia i wyjścia

Co nie powinno być umieszczane w plikach nagłówkowych:

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Zadanie 04 Ktory z ponizszych typow danych w jezyku ANSI C jest typem zmiennoprzecinkowym pojedynczej precyzji?

Programowanie I C / C++ laboratorium 03 arytmetyka, operatory

Podstawy programowania. Wykład: 12. Struktury, unie, pola bitowe. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Wskaźniki. Programowanie Proceduralne 1

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Podstawy programowania. Wykład 6 Złożone typy danych: struktury, unie. Krzysztof Banaś Podstawy programowania 1

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Operatory. Operatory bitowe i uzupełnienie informacji o pozostałych operatorach. Programowanie Proceduralne 1

Wykład 4: Klasy i Metody

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Struktury - wprowadzenie

PROGRAMOWANIE w C prolog

Tablice, funkcje, wskaźniki - wprowadzenie

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Podstawy programowania skrót z wykładów:

Tablice deklaracja, reprezentacja wewnętrzna

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Pobieranie argumentów wiersza polecenia

Część 4 życie programu

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Ćwiczenie 1. Podstawy. Wprowadzenie do programowania w języku C. Katedra Metrologii AGH

Język C - podstawowe informacje

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

Wykład 1

dr inż. Jarosław Forenc

Języki i metodyka programowania. Wprowadzenie do języka C

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Czy procesor musi się grzać?

Podstawy programowania w języku C++

Transkrypt:

Język ANSI C część 14 struktury, unie, pola bitowe Jarosław Gramacki Instytut Informatyki i Elektroniki struktury struktura (słowo kluczowe struct) umożliwia zgrupowanie w pojedynczym rekordzie kilku zmiennych różnych typów (składowych - pól struktury) składowymi struktury mogą być zmienne proste dowolnego typu, tablice, inne struktury, zmienne wskaźnikowe i wskaźniki struktur (w tym wskaźnik do struktury definiowanej) oraz funkcje (C++). Każde pole ma zarezerwowane osobne miejsce w pamięci. pola są umieszczane w pamięci szeregowo zgodnie z kolejnością występowania w strukturze. struktura przechowuje w danym momencie wartości wszystkich swoich składowych. dobry zwyczaj to umieszczanie definicji struktur w plikach nagłówkowych *.h struct osoba char naz[19]; // średnik! unsigned rok, mies, dzien; long id; ; // średnik. jego pominięcie może być trudnym // do znalezienia błędem //lub zamiast ; o1, o2; // deklaracja struktury + deklaracja dwóch zm. strukt. deklaracja struktury (unii) jest wzorcem, który opisuję budowę struktury ważne, w uniach będzie inaczej sama deklaracja typu struktury nie powoduje rezerwacji pamięci, a jedynie określa matrycę według, której będą tworzone zmienne strukturalne dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 2

struktury typedef struct osoba // "nazwany" własny typ danych char naz[19]; unsigned rok, mies, dzien; long id; DANA; //DANA - alternatywna nazwa typu osoba struct osoba w1; DANA w2; // zmienna typu osoba // zmienna typu osoba dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 3 struktury struct osoba char naz[19]; unsigned rok, mies, dzien; long id; o1 = "Kowal", 1985, 11, 9, 123, o2 = "Kostek",1981, 10, 9, 234 ; struct osoba o3 osoba o3 ANSI C C++ struct osoba o3 = "Kowalski", 1984, 6, 15, 345 ; struct osoba o4 = "Nowak" ; // zm. zewn. - pozostałe składowe są zerami static struct osoba o5 = "Nowaczek", 1990 ;// pozostałe pola są zerami o1 = o2; if (o1 == o2) // przypisanie takich samych struktur jest możliwe // błąd. struktur nie wolno porównywać dostęp do danych struktury printf("%s\n", o1.naz); // "Kowal" printf("%u\n%u\n%u\n", o1.rok, o1.mies, o1.dzien); printf("%ld\n", o1.id); printf("\n"); dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 4

wskaźniki do struktur struct osoba char naz[19]; unsigned rok, mies, dzien; long id; ; struct osoba o; struct osoba *po; // zmienna strukturalna // wskaźnik do zmiennej strukturalnej (do struktury) po = &o; // pobranie adresu struktury po -> id = 1234; // nowy operator -> dostępu do pól s. poprzez wskaźnik strcpy(po -> naz, "Gramacki"); printf("%ld\n", po->id); // tak wygodniej printf("%ld\n", (*po).id);// nawiasy konieczne printf("%ld\n", *po.id); // z reguły błąd składniowy. // interpretacja kompilatora: *(po.id) // ale gdy id będzie wskaźnikiem, to błędu składniowego // nie będzie. Błąd logiczny będzie jednak trudno znaleźć printf("%s\n", po->naz); sytuacje podatne na błędy ++po->id; (++po)->id; (po++)->id; przypomnij sobie składnię korzystania ze wskaźników do funkcji // ++(po->id), zwiększenie liczby zamiast wskaźnika // zwiększenie po przed odwołaniem do id // zwiększenie po po odwołaniu do id dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 5 struktury i pola wskaźnikowe struktury mogą zawierać pola typu wskaźnikowego reguły inicjowania i modyfikowania składowych wskaźnikowych są takie same jak w przypadku innych zmiennych wskaźnikowych w szczególności należy pamiętać, aby nie wstawiać danych do obszaru pamięci, który nie został przydzielony struct tosoba char naz[19]; char *imie; // wskaznik do char, patrz inicjacja niżej int *ptr; // wskaźnik do int unsigned r, m, d; long id; z1 = "Kowal", "Adam", (int *)0xB8000000, 1981, 11, 8, 123, z2 = "Nowak", NULL, NULL, 1981, 10, 9, 234 ; gets(z2.imie); // Błąd. Nie wolno wczytywać danych do pamięci wskazywanej // przez niezainicjowane pola wskaźnikowe z2.imie = (char*) malloc (50); gets(z2.imie); // OK strcpy(z2.imie, "Jan"); // OK dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 6

wskaźniki do struktur i pola wskaźnikowe sytuacje podatne na błędy struct int len; char *str; *p; // struktura nienazwana (samo struct) jest poprawna gdy // zaraz po niej pojawia deklaracja zmiennej (tu: *p) ++p->len; // zwiększenie len zamiast zwiększenia wskaźnika gdyż: ++(p->len) *p->str; // udostępnia to na co wskazuje str *p->str++; // zwiększa str po udostępnieniu obiektu wskazywanego przez str // (tak jak *str++) (*p->str)++; // zwiększa to na co wskazuje str *p++->str; // zwiększa p po udostępnieniu obiektu wskazywanego przez str Operators Associativity () [] ->. left to right! ~ ++ -- + - * (type) sizeof right to left // właściwość struktur: wyrównywanie pól struktury struct test char c; int i; ; sizeof(struct test); // = 8,!!!,??? // gdyż wyrównywanie pól struktury // (zależne od implementacji!) // dlatego pliki z zapisanymi strukturami są (prawie zawsze) nieprzenośne dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 7 struktury i funkcje do funkcji można przekazać: + składniki struktury oddzielnie + całą strukturę + wskaźnik do struktury struct point int x; int y; ; struct point * makepoint2(int x, int y) struct point *ptr = (struct point*) malloc(sizeof(struct point); ptr->x = x; ptr->y = y; return ptr; // 2 x makepoint(), Błąd // gdyż nie można rozróżnić // funkcji po liście argumentów struct point makepoint(int x, int y) struct point temp; // zmienna tymczasowa temp.x = x; // x - nazwa pola i nazwa argumentu temp.y = y; // nie ma tu żadnego konfliktu return temp; przeciążanie nazw funkcji: mechanizm C++ struct point addpoint (struct point p1, struct point p2) // brak zmiennej tymczasowej, bo i po co ona... p1.x += p2.x; //... p1, p2 - lokalne kopie p1.y += p2.y; return p1; 2 x addpoint(), OK gdyż różne argumenty funkcji void addpoint (struct point *ptrp1, struct point *ptrp2) // przez wskaźniki ptrp1->x += ptrp2->x; ptrp1->y += ptrp2->y; dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 8

struktury i funkcje // przykładowe wywołania struct point p1 = makepoint(1, 4); struct point p2 = makepoint(10, 40); printf("(%d %d)\n", p1.x, p1.y); printf("(%d %d)\n", p2.x, p2.y); struct point *ptr1 = makepoint2(2, 5); struct point *ptr2 = makepoint2(20, 50); printf("(%d %d)\n", ptr1->x, ptr1->y); printf("(%d %d)\n", ptr2->x, ptr2->y); // utwórz dwa punkty // deklaracja zm. strukt plus ich // inicjalizacja funkcją // utwórz dwa kolejne punkty struct point p3 = addpoint(p1, p2); // struktura przez wartość. // wewnątrz funkcji powstaje ich lokalna kopia printf("(%d %d)\n", p3.x, p3.y); addpoint(ptr1, ptr2); printf("(%d %d)\n", ptr1->x, ptr1->y); // struktura przez wskaźnik // Wynik: (1 4) (10 40) (2 5) (20 50) (11 44) (22 55) dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 9 tablice struktur tablice wskaźników do struktur struct osoba char naz[19]; unsigned rok, mies, dzien; long id; ; analogicznie do "zwykłych" tablic struct osoba T1osoba[100]; struct osoba T2osoba[ ] = "Wojciech", 1999, 12, 5, 177, "Piotr", 1997, 7, 8, 178; struct osoba *T3osoba[2]; // tablica struktur // tablica struktur // tablica (dwóch) wskaźników do struktur gets( T1osoba[5].naz ); T1osoba[5].id = 187; printf("%s\n", T1osoba[5].naz); printf("%s\n", T2osoba[0].naz); printf("%c\n", T2osoba[0].naz[3]); // uwaga na 2 x [] for (int i=0; i<2; i++) T3osoba[i] = &T2osoba[i]; printf("%s\n", (*T3osoba[0]).naz); printf("%s\n", (*T3osoba[1]).naz); // zapełniamy tablicę wskaźników // uwaga na nawiasy dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 10

zapis / odczyt struktur na / z pliku #include <stdio.h> #include <stdlib.h> int main(void) na plik struct personel char name[40]; int id; double height; agent; // agent's data are here char buf[81]; FILE *fptr; long int file_size; struct personel *agent_ptr; // pointer to memory for agents if(!(fptr = fopen("agents.rec", "wb"))) // tryb binarny konieczny printf("\ncan't open file agents.rec"); exit(1); do getchar(); printf("\nenter name: "); gets(agent.name); printf("enter number: "); gets(buf); agent.id = atoi(buf); printf("enter height: "); gets(buf); agent.height = atof(buf); // w pętli po jednym agencie do pliku fwrite ( &agent, sizeof(agent), 1, fptr ); // adres struktury: &agent printf("add another agent (y/n)? "); while(getchar() == 'y'); fclose(fptr); c.d.n dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 11 zapis / odczyt struktur na / z pliku if(!(fptr = fopen("agents.rec", "rb"))) printf("\ncan't open file agents.rec\n"); exit(1); z pliku fseek(fptr, 0, SEEK_END); file_size = ftell(fptr); fseek(fptr, 0, SEEK_SET); // put file ptr at end of file // file size is file pointer // return file ptr to start // allocate memory for entire file if(!(agent_ptr = malloc((size_t)file_size))) printf("\nallocation error"); fclose(fptr); exit(1); // calculate n from file size n = (int)file_size / sizeof(struct personel); // odczyt całej bazy (n agentów) z pliku do pamięci if( fread ( agent_ptr, sizeof(struct personel), n, fptr )!= n) printf("\ncan't read file"); fclose(fptr); exit(1); printf("\nfile read. Total agents is now %d.\n", n); for(int i=0; i<n; i++) printf("%s %d %f: \n", agptr->name, agptr->id, agptr->height); agptr++; fclose(fptr); return 0; dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 12

odczyt pliku do pamięci // wczytaj plik do pamięci (do struktury) #include <stdio.h> #include <stdlib.h> structf = wczytajplik ( FILE * ); Na plik / z pliku; inna wersja typedef struct char *bufor long int wielkosc structf; // dane pliku (ciąg bajtów) // wielkość pliku int main(void) structf dane; FILE *fp; fp = fopen ( "plik.abc", "rb"); dane = wczytajplik ( fp ); fclose( fp); // funkcja wczytajplik() // tu praca z danymi // (UWAGA: zakładamy, że wielkość pliku nie zmieni się) fp = fopen ( "plik.abc", "wb"); fwrite ( dane.bufor, sizeof(char), dane.wielkosc, fp); fclose( fp); // dane na plik return(0); c.d.n dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 13 odczyt pliku do pamięci // wczytaj plik do pamięci (do struktury) Na plik / z pliku; inna wersja structf wczytajplik ( FILE *fp) long int dlugoscpliku; structf dane; fseek ( fp, 0, SEEK_END ); dlugoscpliku = ftell ( fp ); fseek ( fp, 0, SEEK_SET ); // jaki duży plik dane.bufor = ( char * ) malloc ( sizeof(char) * dlugoscpliku); if (!dane.bufor ) exit(1); fread ( dane.bufor, sizeof(char), dlugoscpliku, fp); dane.wielkosc = dlugoscpliku; // cały plik do pamięci return dane; dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 14

unie unia (słowo kluczowe union) jest strukturą, której składowe są umieszczane równolegle w tym samym obszarze pamięci. w danym momencie unia przechowuje wartość tylko jednej składowej - tej, która została zmodyfikowana jako ostatnia. zmienna "unijna" jest wystarczająco obszerna aby pomieścić w sobie wartość największego z typów składowych (zależy to oczywiście od implementacji) unie są podobne do rekordów z wariantami w Pascal-u W strukturach było szeregowo union dana char z[5]; int k; long p; float w; ; union dana u1, u2; // oba słowa: union i dana konieczne w C (w C++ już nie) union // unia bez nazwy typu char z[5]; int k; long p; float w; u1; // nazwa zmiennej teraz konieczna dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 15 unie w przypadku unii wszystkie składowe są pamiętane we wspólnym obszarze pamięci dlatego unię inicjuje się jedną daną odpowiadającą typowi pierwszej składowej jeśli dana jest innego typu to następuje automatyczna konwersja (o ile jest to możliwe) do typu pierwszego pola unii. union dana char z[5]; int k; long p; float w; u1 = 'A', 'B', 'C', u2 = "Ala"; // unie u1, u2 union dana u3 = 65 ; // z[0] = 'A'; pozostałe pola tablicy - zera union dana u4 = (char)66.42 ;// z[0] = 'B'; rzutowanie (char) 66.42 = 66 printf("%s\n", u1.z); // u1 "ABC" printf("%s\n", u2.z); // u2 "Ala" printf("%c\n", u3.z[0]); // u3 A (kod 65) printf("%c\n", u3.z[1]); // u3??? printf("%d\n", u4.k); // u4 66 dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 16

pola bitowe pozwalają oszczędzać pamięć poprzez "upakowanie" informacji do bitów (zamiast np. do całych słów) w przypadku pól typu całkowitego można w deklaracji struktury (unii) określić ile bitów będą one zajmowały zakres wartości, które można przechowywać w danym polu zależy od liczby bitów przydzielonych polu oraz od tego czy jest to pole ze znakiem, czy bez znaku najmniejsza ilość pamięci przeznaczona na pojedyncze pole wynosi 1 bit. Największa wynosi sizeof(int) = 32 pole bitowe definiuje się podając typ danej, nazwę pola i po dwukropku liczbę bitów wykorzystywanych przez pole struct atrybut1 int bit1 : 1; A; struct atrybut2 unsigned bit1 : 1; B; // pole jednobitowe int // pole jednobitowe unsigned Jeśli pole 1-bitowe jest typu signed int (char), to może ono przyjmować wartości 0 lub 1. Jeśli pole jest typu unsigned int (char), to może ono przyjmować wartości 0 lub 1 dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 17 pola bitowe pola bitowe w pewnym sensie są kontrpropozycją dla pewnych zastosowań dyrektywy #define #define JEST 01 #define NIE_MA 02 #define POMIEDZY 04 // wartości muszą być potęgami dwójki // gdyż będziemy potem odpowiednio stosowali op. bitowe // lub enum JEST = 01, NIE_MA = 02, POMIEDZY = 04 ; // alternatywa z polami nitowymi struct unsigned int is : 1; // usigned (tu) konieczne. patrz poprz. strona unsigned int is_not : 1; unsigned int between : 1; flags; // trzy jednobitowe pola // pola zachowują się jak "małe" zmienne całkowite flags.is = flags.is_not = 1; // włączamy bity flags.is_ between = flags.is_not = 0; // wyłączamy bity if (flags.is_not == 0 && flags.is == 0) // czy oba skasowane? dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 18

pola bitowe int main(void) A.bit1 = 1; printf("%d\n", A.bit1); // wartość = -1 A.bit1 = 0; printf("%d\n", A.bit1); // wartość = 0 struct atrybut int bit1 : 1; A; struct atrybut1 unsigned bit1 : 1; B; B.bit1 = 1; printf("%u\n", A.bit1); // wartość = 1 B.bit1 = 0; printf("%u\n", A.bit1); // wartość = 0 return 0; struct atrybut int bit1 : 1; int bity2_10 : 9; int bit11 : 1; int bity12_23 : 12; A; // rozmiar struktury 23 bity int main() A.bit1 = 1; A.bity2_10 = 32; A.bit11 = 1; A.bity12_23 = 1024; printf("%d\n", A.bit1); // -1 printf("%d\n", A.bity2_10); // 32 printf("%d\n", A.bit11); // -1 printf("%d\n", A.bity12_23); // 1024 dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 19 wykorzystanie struktur, liczby zespolone /* * Kod z książki * Programowanie w języku C. FAQ * Addison-Wesley, 1996, ISBN 0-201-84519-9 * (pytanie 14.11) * * Ten kod może być dowolnie używany i modyfikowany, * bez żadnych ograniczeń. */ // complex.h typedef struct double real; double imag; complex; extern complex cpx_make (double, double); extern complex cpx_add (complex, complex); extern complex cpx_subtract (complex, complex); extern complex cpx_multiply (complex, complex); extern char *cpx_print(char *, complex); #define Real(c) (c).real #define Imag(c) (c).imag // asekuracyjnie (c) zamiast c c.d.n. dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 20

wykorzystanie struktur, liczby zespolone // cfun.c #include <stdio.h> #include "complex.h" complex cpx_make (double real, double imag) complex ret; ret.real = real; ret.imag = imag; return ret; // zwracamy strukturę complex cpx_add (complex a, complex b) // pobieramy i zwracamy struktury return cpx_make(real(a) + Real(b), Imag(a) + Imag(b)); complex cpx_subtract (complex a, complex b) return cpx_make(real(a) - Real(b), Imag(a) - Imag(b)); complex cpx_multiply (complex a, complex b) return cpx_make(real(a) * Real(b) - Imag(a) * Imag(b), Real(a) * Imag(b) + Imag(a) * Real(b)); char *cpx_print (char *fmt, complex a) static char retbuf[30]; char *p; sprintf (retbuf, fmt, Real(a)); for(p = retbuf; *p!= '\0'; p++) ; *p++ = '+'; sprintf (p, fmt, Imag(a)); for(; *p!= '\0'; p++) ; *p++ = 'i'; *p = '\0'; return retbuf; zobacz wywołanie tej funkcji na następnej stronie dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 21 wykorzystanie struktur, liczby zespolone // main.c #include <stdio.h> #include "complex.h" int main(void) complex a = cpx_make (1, 2); complex b = cpx_make (3, 4); complex c = cpx_add (a, b); printf("a: %s\n", cpx_print ("%g", a)); printf("b: %s\n", cpx_print ("%g", b)); printf("c=a+b: %s\n", cpx_print ("%g", c)); c = cpx_subtract (a, b); printf("c=a-b: %s\n", cpx_print("%g", c)); c = cpx_multiply (a, b); printf("c=a*b: %s\n", cpx_print("%g", c)); printf("a+b: %s\n", cpx_print("%g", cpx_add(a, b))); printf("1+2i - 3+4i: %s\n", cpx_print("%g", cpx_subtract (cpx_make(1, 2), cpx_make(3, 4)))); complex c = cpx_add(cpx_make(1, 2), cpx_make(3, 4)); printf("c=1+2i + 3+4i: %s\n", cpx_print("%g", c)); c = cpx_multiply(cpx_make(1, 2), cpx_make(3, 4)); printf("c=1+2i * 3+4i: %s\n", cpx_print("%g", c)); return 0; dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 22

wykorzystanie unii, float2bin dzięki unii, możliwe jest "oszukanie" kompilatora, który nie pozwala na stosowanie operatorów bitowych do typów nie-całkowitych #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <math.h> void printtofile(int size, double *digit); int main(int argc, char *argv[]) union float f; double d; unsigned char c[8]; u; int x, i, j, bit; unsigned char mask; You entered: 0.1 if (*argv[1] == 'f') u.f = (float) atof(argv[2]); x = 4; printf("you entered: \n%s\n\n", argv[2]); printf("after converted to float (displayed using printf): \n%.40f\n\n", u.f); printf("displayed as hexadecimal (internal representation): \n%02x %02x %02x %02x\n\n", u.c[0], u.c[1], u.c[2], u.c[3]); else u.d = (double) atof(argv[2]); x = 8; printf("you entered: \n%s\n\n", argv[2]); After converted to float (displayed using printf): 0.1000000014901161190000000000000000000000 Displayed as hexadecimal (internal representation): 3d cc cc cd Displayed as binary (internal representation): 00111101 11001100 11001100 11001101 gdyż kod formatujący %x nie zadziała dla argumentu float! printf("after converted to double (displayed using printf): \n%.40f\n\n", u.d); printf("displayed as hexadecimal (internal representation): \n"); printf("%02x %02x %02x %02x ", u.c[0], u.c[1], u.c[2], u.c[3]); printf("%02x %02x %02x %02x\n\n", u.c[4], u.c[5], u.c[6], u.c[7]); dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 23 wykorzystanie unii, float2bin // convert float to binary printf("displayed as binary (internal representation): \n"); for (i=0; i<x; i++) mask=0x80; if(i>0) printf(" "); for (j=0; j<8; j++) bit = (mask & u.c[i])? 1 : 0; // to już "jest" typ całkowity printf("%d", bit); // można stosować więc operatory bitowe mask >>= 1; if (*argv[1] == 'f') printtofile(4, (double*)&u.f); else printtofile(8, &u.d); return 0; gdyż operator bitowy & nie zadziała dla argumentu float! void printtofile(int size, double *digit) FILE *fptr; fptr = fopen("digit.bin", "wb"); fwrite(digit, size, 1, fptr); fclose(fptr); dr inż. Jarosław Gramacki, Instytut Informatyki i Elektroniki, UZ (ver. 1.19) 24