Język ANSI C

Transkrypt

Język ANSI C
Katedra Elektrotechniki Teoretycznej i
Informatyki
sem. III - wykład 6
04.11.2010
Dr inż. M. Czyżak
Język ANSI C – tablice wielowymiarowe
Przekazywanie tablic w standardzie C99
Standard języka C wprowadzony w roku 1999 (C99) wprowadził istotne
zmiany w stosunku do ANSI C. Nie jest on w pełni realizowany przez dostępne
kompilatory, istotna część zmian wprowadzonych przez ten standard jest jednak
uwzględniona w kompilatorze GNU C, który stanowi podstawę DevC++.
Jedna z najbardziej istotnych zmian pojawia się przy przekazywaniu tablic
wielowymiarowych do funkcji, gdzie wszystkie rozmiary przekazywanej tablicy
mogą być zmiennymi, a nie stałymi ( poza pierwszym rozmiarem), jak to ma
miejsce w ANSI C.
W C99 rozmiar tablicy w funkcji może być zwykłą zmienną lokalną lub
parametrem funkcji ( są to tzw. variable-length arrays).
Język ANSI C – tablice wielowymiarowe
Przekazywanie tablic w standardzie C99
Przykład. Wczytywanie i drukowanie tablic w standardzie
C99.(cz.1)
#include <stdio.h>
void
wczyt2DC99( int n, int m, int x[n][m])
// ilosc kolumn nie musi być stałą, może być podana jako parametr
{
int i,j;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{ printf("\n Element [%d][%d]=",i,j);
scanf("%d",&x[i][j]);
}
}
Język ANSI C – tablice wielowymiarowe
Przekazywanie tablic w standardzie C99
Przykład. Wczytywanie i drukowanie tablic w standardzie C99.(cz.2)
void
druk2DC99( int n, int m, int x[n][m])
{
int i,j;
for (i=0;i<n;i++)
{ for (j=0;j<m;j++)
printf("
%d", x[i][j]);
printf("\n");
}
}
Język ANSI C – tablice wielowymiarowe
Przekazywanie tablic w standardzie C99
Przykład. Wczytywanie i drukowanie tablic w standardzie C99.(cz.3)
int main()
{
int a[2][2], b[3][3];
wczyt2DC99(2,2,a);
wczyt2DC99(3,3,b);
druk2DC99( 2,2,a);
druk2DC99( 3,3,b);
system("pause");
return 0;
}
// Tablice przekazywane do funkcji mają różne rozmiary
// ilość kolumn nie musi być taka sama
Wyniki działania programu
Element [0][0]=1
c.d.
Element [0][1]=2
1 2 3
Element [1][0]=3
4 5 6
Element [1][1]=4
7 8 9
1 2
3 4
Element [0][0]=1
Element [0][1]=2
Element [0][2]=3
Element [1][0]=4
Element [1][1]=5
Element [1][2]=6
Element [2][0]=7
Element [2][1]=8
Element [2][2]=9
Język ANSI C – operatory bitowe
Język C pozwala programiście na bezpośrednie współdziałanie ze sprzętem
poprzez użycie operatorów bitowych i wyrażeń bitowych. Operatory bitowe
umożliwiają działanie na pojedynczych bitach. Operatory te działają wyłącznie z
typami całkowitymi np. takimi jak char czy też int.
Aby stosować operatory bitowe w danym systemie powinno się zgromadzić
następujące informacje:
- liczba bitów, które tworzą bajt,
- liczba bajtów dla typów całkowitych,
- system kodowania znaków (np. ASCII)
- typ stosowanej reprezentacji liczb ujemnych (np. kod U2)
Poniżej założymy 8-bitowy bajt i 16-bitową komórkę dla przechowywania
liczb całkowitych oraz kod U2.
Język ANSI C – operatory bitowe
Operatory bitowe to:
- ‘ ~ ‘ - bitowy operator uzupełnienia do 1,
-’&’
- bitowy operator koniunkcji (iloczynu logicznego),
-’ | ‘
- bitowy operator alternatywy (sumy logicznej),
- ’^’
- bitowy operator różnicy symetrycznej (XOR),
- ‘<<‘ - bitowy operator przesunięcia w lewo,
- ‘>>’ - bitowy operator przesunięcia w prawo.
Język ANSI C – operatory bitowe
Bitowy operator uzupełnienia do 1, ‘ ~ ‘
Operator ten (zwany tyldą), neguje poszczególne bity swojego
argumentu (zamienia zera na jedynki, a jedynki na zera).
Przykład. Użycie bitowego operatora uzupełnienia do 1.
#include <stdio.h>
int main ()
{
short int
x,y;
x=6;
y=~x;// użycie operatora ~
printf(" Wartosc y=%d \n", y);
system("pause");
return 0;
}
Język ANSI C – operatory bitowe
Wartość ~x wynosi 7. Wynika to ze stosowania kodu U2 do
reprezentowania liczb ujemnych. Liczba 6 ma następującą reprezentację
binarną
0000 0000 0000 0110
Po negacji otrzymujemy
1111 1111 1111 1001 czyli -7 w U2.
Można to łatwo sprawdzić:
+7
0000
0000 0000 0111
-7 w U1
1111
1111 1111 1000,
czyli po dodaniu 1, otrzymujemy 1111 1111 1111 1001)
Język ANSI C – operatory bitowe
Rozszerzenie znakowe ( ang. sign extension)
W operacjach wykonywanych na bitach występuje problem konwersji
pomiędzy różnymi formatami liczb całkowitych (np. char i short int).
Przy konwersjach takich istnieje konieczność zachowania wartości
konwertowanej liczby. Dla liczb ujemnych przy przechodzeniu z formatu
krótszego na dłuższy, wszystkie bity starsze, które nie występowały w
formacie krótszym zamieniane są na 1. Działanie, określane jako
rozszerzenie znakowe, nie powoduje zmiany wartości liczby ujemnej.
Język ANSI C – operatory bitowe
Przykład. Rozszerzenie znakowe.
Dana jest liczba
- 6 w kodzie U2 umieszczona w komórce 8-bitowej
0000 0110
+ 6 w U2,
1111 1001
- 6 w U1
1111 1010
- 6 w U2
Po rozszerzeniu do 16 bitów mamy
1111 1111 1111 1010
Można sprawdzić, że kod ten reprezentuje -6 w U2.
+ 6 0000 0000 0000 0110,
- 6 w U1 1111 1111 1111 1001,
-6 w U2 1111 1111 1111 1010
Język ANSI C – operatory bitowe
Bitowe operatory logiczne
-’&’
- bitowy operator koniunkcji (iloczynu logicznego),
-’ | ‘
- bitowy operator alternatywy (sumy logicznej),
- ’^’
- bitowy operator różnicy symetrycznej (XOR).
Operatory te działają niezależnie na parach bitów o tej samej wadze
obydwu swoich argumentów.
Wyniki działania poszczególnych operatorów pokazano w tabeli.
Dla dwóch danych bitów b1 i b2 otrzymujemy:
b1
b2
b1&b2
b1|b2
b1^b2
0
0
0
0
0
0
1
0
1
1
1
0
0
1
1
1
1
1
1
0
Język ANSI C – operatory bitowe
Przykład. Działania z zastosowaniem operatorów bitowych
Dane są następujące definicje
short int lanbit1=12;
short int lanbit2=-35
lanbit1
0000 0000 0000 1100
lanbit2
1111 1111 1101 1101
Wykonać podane poniżej działania w programie i poprzez obliczenia na liczbach
binarnych
1. ~lanbit1
-13
2. ~lanbit2
34
3.lanbit1&lanbit2
12
4.~lanbit1&lanbit2
-47
5.~(lanbit1&lanbit2)
-13
6.lanbit1| lanbit2
-35
7.~(lanbit1|lanbit2)
34
8.(~lanbit1|lanbit2)
-1
9.
lanbit1^lanbit2
10. ~(lanbit1^lanbit2)
-47
46
Język ANSI C – operatory bitowe
Przykład. Wyznaczanie reprezentacji binarnej liczby 8-bitowej.
#include <stdio.h>
#include <conio.h>
int main()
{
char x=12;
int i,k=1, bit[8];
for (i=0;i<8;i++)
{
if (x&k) bit[i]=1; else bit[i]=0;
k*=2; // k=k*2
}
for (i=7;i>=0;i--) printf("
getch();
return 0;
}
%d ",bit[i]);
Język ANSI C – operatory bitowe
Operatory przesunięć bitowych (ang. bitshift operators)
Operatory bitowe przesuwają bity swego argumentu znajdującego
się po lewej stronie operatora o zadaną liczbę bitów w lewo lub w
prawo. Wyrażenia z użyciem tych operatorów można zapisać
następująco:
E1<< E2
lub
E1>>E2,
gdzie E1 reprezentuje wzorzec bitowy, który ma zostać przesunięty,
operator << oznacza przesunięcie w lewo, a operator >>
przesunięcie w prawo, E2 określa liczbę przesunięć.
Język ANSI C – operatory bitowe
Jeśli nie ma nadmiaru arytmetycznego, dla operatora <<
przesunięcie jest równoważne mnożeniu przez
2E 2
, a na najmłodsze
pozycje pierwszego argumentu wchodzą zera. Działanie operatora >>
odpowiada dzieleniu całkowitemu przez
2E 2
dla typów bez znaku
( unsigned), wtedy na skrajne pozycje z lewej strony wchodzą zera.
Dla typów ze znakiem, jeżeli wchodzą zera dla liczb nieujemnych, a
jedynki dla liczb ujemnych mówimy o przesunięciu arytmetycznym, a
jeżeli zera niezależnie od znaku liczby, to jest to tzw. przesunięcie
logiczne.
Język ANSI C – operatory bitowe
Przykład. Użycie operatorów bitowych przesunięcia w lewo i w prawo.
#include <stdio.h>
#include <conio.h>
int main() {
int x1='A', x2='0';
int y1=3,y2=2;
printf("\n %d", x1<<y1);// kod ASCII
//
znaku ‘A’ jest równy 65
stąd w wyniku przesunięcia otrzymujemy 520
printf("\n %d ", x2>>y2); // przesunięcie
prawo o 2 odpowiada
// dzieleniu całkowitemu przez 4, otrzymujemy
getch();
}
12
Język ANSI C – operatory bitowe
Przykład. Ustawianie określonego bitu w słowie na 1.
Ustawianie bitu o numerze nrBitu na 1
x= x | 1<< nrBitu;
Najpierw realizowane jest przesunięcie reprezentacji bitowej liczby 1 o
nrBitu bitów w lewo, odpowiada to wstawieniu 1 na określoną pozycję,
(jedynka w reprezentacji liczby 1 będąca na najmłodszej pozycji zostanie
przesunięta w lewo, a z prawej strony wejdą zera), następnie
wykonywana jest suma logiczna liczby x i liczby otrzymanej w wyniku
działania 1<< nrBitu . Powoduje to ustawienie bitu o numerze nrBitu
liczby x na 1 ( jeśli bit ten był równy 1, to suma logiczna nie spowoduje
zmiany, jeżeli był on równy 0, wykonanie sumy spowoduje ustawienie go
na 1).
Język ANSI C – operatory bitowe
Przykład. Ustawianie określonego bitu w słowie na 0.
Ustawianie bitu o numerze nrBitu na 0
x= x & ~(1<<nrBitu);
Działanie 1<<nrBitu opisano powyżej. Daje ono słowo, gdzie bit o
wartości 1 jest na pozycji o numerze nrBitu, pozostałe bity liczby są
równe zeru. Negacja tej liczby ( operator ~)daje słowo, które ma same
jedynki poza zerem na pozycji nrBitu. Realizacja iloczynu logicznego
tego słowa i x powoduje, że na miejsce bitu o numerze nrBitu wstawiane
jest 0, a pozostałe bity nie zmieniają się.
Język ANSI C – operatory bitowe
Przykład. Dane jest słowo 8-bitowe. Napisać funkcję wyznaczającą wartość
dziesiętną bloku n-bitowego począwszy od pozycji p ( pozycja ma wagę
2p
).
int oblWartBloku (char
x, int n, int p)
// n – liczba bitów, p – pozycja ( pozycje numerowane od 0)
{
return x>>(p+1-n)& ~( ~0<<n);
}
Zasada działania funkcji tej jest następująca:
- przesunięcie bloku n-bitowego na najmłodsze pozycje ( pozycje o wagach od
n −1
1 do 2
), jest to realizowane poprzez działanie x >> (p+1-n)
- utworzenie maski wycinającej n najmłodszych bitów ze słowa 8-bitowego
( maska ta ma 1 na n najmłodszych bitach i 0 na pozostałych)
- obliczenie iloczynu bitowego przesuniętego bloku n-bitowego i maski.
Język ANSI C – operatory bitowe
Przykład. Zastosowanie funkcji oblWartBloku.
#include <stdio.h>
#include <conio.h>
int oblWartBloku (char
x, int n, int p);
int main() {
int x=23;
int p=4;
int n=3;
x=oblWartBloku(x,n,p);
printf("%d",x);// x=5,z reprezentacji binarnej
liczby
23
// równej (1,0,1,1,1), wyodrębniany jest
// blok złożony z trzech najstarszych bitów
getch(); return 0;}
int oblWartBloku (char
x, int n, int p)
// n – liczba bitów, p – pozycja( pozycje numerowane od 0)
{ return x>>(p+1-n)& ~(~0<<n);}

Podobne dokumenty