Definicje zmiennych i deklaracje
Sta艂e
Operatory
Wyra偶enia
Instrukcje
Tablice i wska藕niki
Struktury
Inicjowanie zmiennej
Funkcje
Argumenty funkcji main
聽
聽
Definicje zmiennych i deklaracje
Zmienne musz膮 by膰 zdefiniowane przed u偶yciem. Dost臋pne s膮 nast臋puj膮ce podstawowe typy danych:
Typ | Definicja | Typowy rozmiar |
---|---|---|
char | zmienna znakowa | 1 bajt |
short int | liczba znakowa kr贸tka | 2 bajty |
int | liczba ca艂kowita | zale偶y od realizacji |
long int | liczba ca艂kowita d艂uga | 4 bajty |
float | liczba zmiennoprzecinkowa | 4 bajty |
double | liczba zmiennoprzecinkowa o podw贸jnej precyzji | 8 bajt贸w |
long double | liczba zmiennoprzecinkowa d艂uga | zale偶y od realizacji np. 80 bit贸w |
unsigned char | zmienna znakowa bez znaku | 1 bajt |
unsigned int | liczba ca艂kowita bez znaku | zale偶y od realizacji |
Podane s膮 rozmiary najcz臋艣ciej u偶ywane, ale programista powinien sprawdzi膰 rozmiar dla u偶ywanego kompilatora.
Wyst臋puj膮 jeszcze inne typy danych:
- tablica, czyli wielokrotne wyst膮pienie identycznych zmiennych;
- struktura, czyli grupa powi膮zanych zmiennych; mog膮 by膰 r贸偶nych typ贸w;
- wska藕nik, czyli zmienna zawieraj膮ca adres innej zmiennej;
- unia, czyli dwie lub wi臋cej zmiennych zajmujacych w pami臋ci to samo miejsce;
- dane wyliczeniowe (enum), czyli zmienne o ograniczonym zbiorze dopuszczalnych warto艣ci;
- ci膮g znak贸w (艂a艅cuch), czyli tablica zmiennych znakowych typu char, zako艅czona znakiem NULL.
Dodatkowe typy danych, oparte na podanych powy偶ej, mo偶na zdefiniowa膰 korzystaj膮c ze specyfikatora typedef. R贸偶nica mi臋dzy definicj膮 danych a deklaracj膮 danych polega na tym, 偶e definicja danych rezerwuje miejsce w pami臋ci na dane, a deklaracja nie.
Zmienne zdefiniowane lub zadeklarowane poza funkcjami s膮 dost臋pne od miejsca zdefiniowania a偶 do ko艅ca pliku 藕r贸d艂owego. Zmienne zdefiniowane wewn膮trz funkcji s膮 dost臋pne jedynie wewn膮trz tych funkcji, w kt贸rych zosta艂y zdefiniowane. Zmienne zdefiniowane wewn膮trz instrukcji z艂o偶onych (blok贸w) s膮 dost臋pne jedynie wewn膮trz tych instrukcji z艂o偶onych, w kt贸rych zosta艂y zdefiniowane.
Zmienne mog膮 nale偶e膰 do jednej z czterech klas:
- static - pami臋膰 dla nich jest rezerwowana statycznie na pocz膮tku programu;
- auto - pami臋膰 dla nich jest rezerwowana dynamicznie, gdy funkcja jest wykonywana i jest zwalniana, gdy ko艅czy si臋 wykonanie funkcji (jest to domy艣lna klasa pami臋ci dla zmiennych definiowanych wewn膮trz funkcji);
- extern - pami臋膰 dla nich jest rezerwowana w innym pliku; odwo艂anie rozstrzyga konsolidator;
- register - s膮 zapami臋tywane w rejestrach, o ile jest to mo偶liwe;
聽
Sta艂e
Sta艂e s膮 okre艣lane w tek艣cie programu nast臋puj膮co:
Typ | Sk艂adnia | Przyk艂ad |
---|---|---|
char | otoczona apostrofami | 'a' |
ci膮g znak贸w | otoczona cudzys艂owami | "abc" |
liczba 贸semkowa | zaczyna si臋 0 (zerem) | 0377 |
liczba szesnastkowa | zaczyna si臋 0x | 0x3ef |
long int | ko艅czy si臋 l lub L | 123L |
float | z kropk膮 dziesi臋tn膮 lub w notacji naukowej | 3.24 lub 3.2E-4 |
double | jak double | 聽 |
聽
Operatory
operator | opis operatora | przyk艂ad |
---|---|---|
operatory nawiasowe i selektorowe | ||
() | wywo艂anie funkcji | getc(stdin) |
[] | odwo艂anie do elementu tablicy | k[17] |
-> | selekcja pola struktury lub unii wskazywanej przez wska藕nik | wsu -> pole |
. | odwo艂anie do elementu struktury | su.c |
operacje jednoargumentowe | ||
! | negacja logiczna | !1 daje 0 !0 daje 1 |
~ | uzupe艂nienie do jedynki lub negacja bitowa | ~0x7f |
+ | plus jednoargumentowy | +n |
- | minus jednoargumentowy | -n |
++ | preinkrementacja lub postinkrementacja |
++i i++ |
-- | dekrementacja | --i lub i-- |
* | wkazanie po艣rednie (wy艂uskanie) | *p_k |
& | adres elementu | &n |
sizeof | rozmiar zmiennej lub typu | sizeof(j*z) lub sizeof(k) lub sizeof(float) |
(typ) | zmiana typu | (int) frac |
Przyk艂ady
j=++i <==> i=i+1;
j=i; j=i++ <==> j=i; i=i+1;
operator | opis operatora | przyk艂ad |
---|---|---|
operatory multiplikatywne | ||
* | mno偶enie | i*j |
/ | dzielenie | i/j |
% | dzielenie modulo | i%j |
operatory addytywne | ||
+ | dodawanie | i+j |
- | odejmowanie | i-j |
operatory przesuni臋膰 bitowych | ||
<< | pzesuni臋cie bitowe w lewo | i<<2 |
>> | pzesuni臋cie bitowe w prawo | i>>2 |
operatory por贸wna艅 | ||
< | mniejszy ni偶 | i<j |
<= | mniejszy lub r贸wny | i<=j |
> | wi臋kszy ni偶 | i>j |
>= | wi臋kszy lub r贸wny | i>=j |
== | r贸wny | if (i==5) |
!= | nier贸wny | if (i!=5) |
operatory bitowe dwuargumentowe | ||
& | bitowy iloczyn logiczny (AND) | c&033 |
^ | bitowa suma modulo 2 (XOR) | c^0317 |
| | bitowa suma logiczna | c|0333 |
operatory logiczne dwuargumentowe | ||
&& | iloczyn logiczny (AND) | i==5 && j==6 |
|| | suma logiczna (OR) | i==5 || j==6 |
operator warunkowy | ||
?: | wyb贸r jednego z dw贸ch wyra偶e艅 | max=(i>j?i:j) |
operatory przypisa艅 | ||
= | proste przypisanie | i=7 |
*= | mno偶enie, potem przypisanie | i*=3 czyli i=i*3 |
/= | dzielenie, potem przypisanie | i/=4 |
%= | dzielenie modulo, potem przypisanie | i%=4 |
+= | dodawanie, potem przypisanie | i+=5 |
-= | odejmowanie, potem przypisanie | i-=5 |
&= | iloczyn bitowy, potem przypisanie | i&=0333 |
^= | suma mod 2, potem przypisanie | i^0317 |
|= | suma logiczna, potem przypisanie | i|=0117 |
<<= >>= |
przesuni臋cie w lewo (w prawo), potem przypisanie | i<<=2 i>>=3 |
operator wyliczenia | ||
, | oblicznenie i odrzucenie | func (j, (i=2, i+4), k) |
聽
Wyra偶enia
Wyra偶enie mo偶e przyj膮膰 jedn膮 z nast臋puj膮cych postaci:
- nazwa zmiennej,
- wywo艂anie funkcji,
- nazwa tablicy,
- sta艂a,
- nazwa funkcji,
- odwo艂anie do elementu struktury,
- odwo艂anie do elementu tablicy,
- jedna z powy偶szych postaci z nawiasami i operatorami.
聽
Instrukcje
Wyra偶enie zako艅czone 艣rednikiem jest uwa偶ane za instrukcj臋. Na przyk艂ad: i+1 jest wyra偶eniem, podczas gdy i+1; jest instrukcj膮. Oto przyk艂ady innych instrukcji:
; instrukcja pusta
if (wyrazenie) instrukcja
if (wyra偶enie) instrukcja1 else instrukcja2
while (wyra偶enie) instrukcja
do instrukcja while (wyra偶enie);
for (wyra偶enie1; wyra偶enie2; wyra偶enie3) instrukcja
break;
switch (wyra偶enie_ca艂kowitoliczbowe) {case sta艂a1: instrukcja1 break; case sta艂a2: instrukcja2 break; . . . . default: instrukcja break;}
continue;
goto etykieta;
return;
return wyra偶enie;
聽
Tablice i wska藕niki
Wska藕nik jest to zmienna zawieraj膮ca adres innej zmiennej. W j臋zyku C wska藕niki maj膮 okre艣lony typ, to znaczy, 偶e standardowo definiuje si臋 je jako wska藕niki do zmiennej okre艣lonego typu, np:
char *c - wska藕nik do zmiennej typu znakowego
int *p - wska藕nik do zmiennej typu ca艂kowitego
char *argv[] - wska藕nik do tablicy, kt贸rej elementami s膮 ci膮gi znak贸w.
Definicja int *p_k okre艣la zmienn膮 p_k jako wska藕nik do zmiennej ca艂kowitej, natomiast wyra偶enie *p_k oznacza "zmienna wskazywana przez p_k" . W przypadku wska藕nik贸w dopuszcza si臋 tylko proste operacje arytmetyczne. Do wska藕nika mo偶na doda膰 (lub od niego odj膮膰) tylko liczb臋 ca艂kowit膮, ale nie s膮 dopuszczalne operacje w zasadzie bezsensowne, takie jak dodawanie wska藕nik贸w, dzielenie wska藕nika przez liczb臋 ca艂kowit膮 itp.
Tablica jest to ci膮g zmiennych tego samego typu zajmuj膮cych ci膮g艂y obszar w pami臋ci. Na przyk艂ad definicja int k[10] okre艣la tablic臋 dziesi臋ciu liczb ca艂kowitych, o nazwach od k[0] do k[9]. Zauwa偶my, 偶e w j臋zyku C pierwszy element tablicy ma numer 0. W j臋zyku C nazwa tablicy (bez nawiasu kwadratowego) jest rozumiana nie jako warto艣膰 pierwszego elementu tablicy, lecz jako jej adres. Tak wi臋c wyra偶enie p_k = k ustawia tak p_k , aby wskazywa艂 on pierwszy element tablicy k. Je偶eli p_k wskazuje element k[0], to p_k + 1 wskazuje element k[1]. Tak wi臋c inkrementacja wska藕nika nie zwi臋ksza go o jeden bajt, ale o jeden element. Innymi s艂owy, istniej膮 dwie metody odwo艂ywania si臋 do elementu tablicy - przez u偶ycie indeksu w tablicy (np. k[3]) lub odpwiednio zdefiniowanego wska藕nika (np. *(p_k + 3) ).
Przyk艂ady:
char c[5] = {'a','b','c','d','\0'} - definiuje tablic臋 znakow膮 typu char o nazwie c, z艂o偶on膮 z 5 element贸w, kt贸rej przypisano warto艣ci pocz膮tkowe od 'a' do 'd' i zako艅czono znakiem ko艅ca ci膮gu znak贸w
char *string = c - definiuje zmienn膮 string jako wska藕nik do zmiennej typu char i nadaje jej warto艣膰 pocz膮tkow膮 c, tak aby wskazywa艂a tablic臋 c
int *p[4] - definiuje tablic臋 4 wska藕nik贸w do liczb ca艂kowitych
int (*p[4]) () - definiuje tablic臋 4 wska藕nik贸w do funkcji, daj膮cych w wyniku liczby ca艂kowite
int k[3] [4] - definiuje tablic臋 dwuwymiarow膮 o rozmiarze 3x4: k[0][0], k[0][1], k[0][2], k[0][3] k[1][0], k[1][1], k[1][2], k[1][3] k[2][0], k[2][1], k[2][2], k[2][3]
Nazwa tablicy jest sta艂膮 maj膮c膮 znaczenie jej pierwszego elementu. W tablicach wielowymiarowych, jak tablica powy偶ej, sta艂a k jest adresem elementu k[0][0] (zmiennej. Sta艂a k[0] jest adresem pierwszego elementu pierwszego wiersza tablicy, to jest k[0][0]. Sta艂a k[1] jest adresem pierwszego elementu drugiego wiersza tablicy, to jest k[1][0] itd.
Wska藕niki do zmiennych u偶ywane s膮 tak偶e w innych sytuacjach:
1. Sytuacje, w kt贸rych wymagania na rozmiar pami臋ci nie da si臋 okre艣li膰 w chwili kompilacji i pami臋膰 musi by膰 przydzielona dynamicznie. Nie zawsze bowiem wiadomo dok艂adnie, jak du偶a tablica jest potrzebna i dynamiczny przydzia艂 pami臋ci z u偶yciem np. funkcji malloc i free pozwala optymalizowa膰 wykorzystanie pami臋ci.
2. Umo偶liwienie funkcjom modyfikowanie zmiennych, kt贸re s膮 dla nich niewidoczne. W j臋zyku C funkcja mo偶e zmodyfikowa膰 warto艣膰 zmiennej, kt贸rej nie widzi, pod warunkiem, 偶e widzi wska藕nik do niej, je偶eli ten wska藕nik zosta艂 zdefiniowany globalnie lub jest jednym z argument贸w funkcji.
Przyk艂ad
int i; int k;
funkc(&i, k); - wywo艂anie funkcji
void func(j, n) - definicja funkcji
{
int *j; int n;
*j = 1; - nadanie i warto艣ci 1
n = *j; - nie ma wp艂ywu na k
}
聽
Struktury
Struktura (s艂owo kluczowe w postaci struct) jest to zbi贸r logicznie powi膮zanych zmiennych r贸偶nych typ贸w, odpowiadaj膮cych rekordowi w j臋zyku Pascal. Struktury mo偶na okre艣li膰 na jeden z trzech sposob贸w:
1. struct complex
{
double real;
double imaginery;
}
Zadeklarowano tu struktur臋 o nazwie complex, ale nie zdefiniowano 偶adnej zmiennej. Definicje podane poni偶ej s膮 poprawne pod warunkiem, 偶e odbywaj膮 si臋 w zasi臋gu powy偶szej deklaracji:
struct complex c1;
struct complex *c1;
struct complex *func();
struct complex c[2];
2. struct
{
double real;
double imaginery;
} c;
Zadeklarowano tu nie nazwan膮 struktur臋 i zdefiniowano pojedyncz膮 zmienn膮 tego typu. Poniewa偶 ta struktura nie ma oznacznika, nie jest wi臋c mo偶liwe zdefiniowanie innych zmiennych lub wska藕nik贸w do struktury tego typu.
3. struct complex
{
double real;
double imaginery;
} c[2];
Zadeklarowano tu struktur臋 o nazwie complex i zdefiniowano tablic臋 dw贸ch zmiennych typu struct complex. Definicje i deklaracje podane dla pierwszego przyk艂adu s膮 tak偶e tutaj dopuszczalne pod warunkiem, 偶e znajduj膮 si臋 w zasi臋gu tej deklaracji.
Elementami struktury mog膮 by膰 zmienne dowolnego typu. Wska藕nik do deklarowanej struktury mo偶e by膰 zdefiniowany jako jeden z jej element贸w. Taka w艂a艣ciwo艣膰 nosi nazw臋 autoreferencji struktury.
struct node
{
struct node *parent;
struct node *right_child;
struct node *left_child;
char c;
};
Do poszczeg贸lnych element贸w struktury mo偶na si臋 odwo艂ywa膰 w r贸偶ny spos贸b. Przy podanych ni偶ej deklaracjach i definicjach:
struct complex
{
double real;
double imaginery;
} c;
struct complex *p_c = c;
Wyra偶enie p_c jest wska藕nikiem do struktury c.
Wyra偶enia
- c.real
- (*p_c).real
-p_c -> real
odnosz膮 si臋 do zmiennej real w strukturze c.
聽
Inicjowanie zmiennej
Definicja zmiennej mo偶e tak偶e zawiera膰 nadanie jej warto艣ci poczatkowej (inicjowanie). Sk艂adnia jest nast臋puj膮ca:
- dla zmiennych prostych definicja = wyra偶enie;
- dla agregat贸w (struktur i tablic) definicja = {lista_warto艣ci_pocz膮tkowych};
Unie i agregaty klasy auto nie mog膮 by膰 inicjowane. Wyra偶enie musi by膰 sta艂膮 lub wynikiem jego obliczenia musi by膰 sta艂a albo adres poprzednio zadeklarowanej zmiennej (ewentualnie przesuni臋ty o sta艂膮 warto艣膰). Lista_warto艣ci_pocz膮tkowych jest list膮 warto艣ci dla element贸w agregatu, oddzielonych przecinkami, w kolejno艣ci rosn膮cych numer贸w tych element贸w. Zmienne klasy auto lub register mog膮 dodatkowo by膰 inicjowane za pomoc膮 wyra偶e艅 zawieraj膮cych wywo艂anie funkcji lub za pomoc膮 poprzednio zdefiniowanych lub zadeklarowanych zmiennych, gdy偶 inicjuje si臋 podczas wykonywania programu, a nie podczas kompilacji. W przypadku inicjowania agregatu, je艣li liczba element贸w w li艣cie warto艣ci pocz膮tkowych jest mniejsza ni偶 liczba element贸w agregatu, to pozosta艂ym elementom agregatu nadaje si臋 warto艣膰 zero. Tablicy znakowej mo偶na nada膰 warto艣膰 pocz膮tkow膮 za pomoc膮 ci膮gu znak贸w.
Przyk艂ady
int i = 3;
int k[4] = { 0, 4, 6, 9};
int k[] = {5, 10, 8};
int m[4] = {1,2};
int n[4][3] = { {1,2,3}, {4,5,6} }; - definiuje nast臋puj膮c膮 tablic臋:
n[0][0] = 1 n[0][1] = 2 n[0][2] = 3
n[1][0] = 4 n[1][1] = 5 n[1][2] = 6
n[2][0] = 0 n[2][1] = 0 n[3][2] = 0
int n[4][3] = { 1,2,3, 4,5,6 }; - definiuje tak膮 sam膮 tablic臋, jak poprzednio
int q[4][3] = { {1}, {2}, {3}, {4} }; - definiuje tablic臋 2-wymiarow膮 w nast臋puj膮cy spos贸b:
q[0][0] = 1 q[1][0] = 2
q[2][0] = 3 q[3][0] = 4
Pozosta艂ym elementom tablicy nadaje si臋 warto艣膰 zero.
Instrukcja char *ostrze偶enie = "Uwa偶aj na zakr臋tach" definiuje ci膮g znak贸w tak du偶y, aby zmie艣ci艂 si臋 w nim tekst, stanowi膮cy jego warto艣膰 pocz膮tkow膮, 艂膮cznie zko艅cz膮cym ka偶dy ci膮g znak贸w znakiem '\0'.
Instrukcja
struct
{
char *s艂owo;
int licznik;
} start [4] = { "witaj", 0, "偶egnaj", 0 };
definiuje tablic臋 4 struktur, przy czym pierwszym pierwszym dw贸m elementom tablicy (strukturom) nadaje si臋 nast臋puj膮ce warto艣ci:
start[0].s艂owo = "witaj"
start[0].licznik = 0
start[1].s艂owo = "偶egnaj"
start[1].s艂owo = 0
Pozosta艂ym elementom struktury przypisuje si臋 warto艣膰 zero.
聽
Funkcje
We wszystkich plikach 藕r贸d艂owych, kt贸re s膮 kompilowane i konsolidowane w celu utworzenia programu wynikowego, tylko jedna funkcja mo偶e nosi膰 nazw臋 main. Pierwsza wykonywana instrukcja instrukcja w programie jest te偶 pierwsz膮 wykonywaln膮 instrukcj膮 w main.
W j臋zyku C wszystkie funkcje znajduj膮 si臋 na tym samym poziomie sk艂adniowym; nie mo偶na definiowa膰 funkcji wewn膮trz funkcji. Co wi臋cej, wszystkie funkcje we wszystkich plikach tworz膮cych program oraz wszystkie funkcje w bibliotekach do艂膮czonych przez konsolidators膮 widoczne dla wszystkich pozosta艂ych funkcji. Jedynym wyj膮tkiem jest funkcja okre艣lana jako static; jej widoczno艣膰 jest ograniczona do pliku 藕r贸d艂owego, w kt贸rym zosta艂a zdefiniowana.
Funkcja mo偶e by膰 wywo艂ywana z argumentami, kt贸re s膮 przekazywane przez warto艣膰. W j臋zyku C nie wyst臋puje wywo艂anie przez nazw臋, gdy偶 wywo艂ana funkcja otrzymuje kopi臋 argumentu i nie jest w stanie zmieni膰 warto艣ci oryginalnej zmiennej. Wyj膮tek stanowi膮 argumenty b臋d膮ce tablic膮; w tym wypadku przekazuje si臋 wska藕nik do tablicy, a nie sam膮 tablic臋, poniewa偶 - jak zauwa偶yli艣my wcze艣niej - przez nazw臋 tablicy rozunie si臋 jej adres. W niekt贸rych wersjach j臋zyka C jest mo偶liwe wywo艂anie struktury przez nazw臋.
Funkcja nie mo偶e modyfikowa膰 warto艣ci swoich argument贸w (z wyj膮tkiem dw贸ch wypadk贸w wywo艂ania przez nazw臋 om贸wionych wy偶ej). Mimo to funkcja mo偶e modyfikowa膰 warto艣膰 zmiennej niewidocznej dla niej, je艣li widzi ona adres tej zmiennej jako sw贸j argument albo jako zmienn膮 globaln膮.
Funkcja mo偶e zwraca膰 wynik za pomoc膮 instrukcji return. Je艣li funkcja nie zwraca 偶adnego wyniku poprzez swoj膮 nazw臋, to w nag艂贸wku funkcji podaje si臋 modyfikator void. Mo偶liwe jest przekazanie jako argumentu funkcji nazwy innej funkcji, zwanej "wska藕nikiem do funkcji". Cia艂o funkcji, to jest definicje, deklaracje i instrukcje, musi by膰 zawarte w nawiasach klamrowych.
Przyk艂ady deklaracji funkcji
deklaracja | znaczenie |
---|---|
int f() | f jest funkcj膮 daj膮c膮 w wyniku liczb臋 ca艂kowit膮 |
int *f() | f jest funkcj膮 daj膮c膮 w wyniku wska藕nik do zmiennej ca艂kowitej |
int (*) f() | f jest wska藕nikiem do funkcji daj膮cej w wyniku liczb臋 ca艂kowit膮 |
int (*f[4])() | f jest tablic膮 4 wska藕nik贸w do funkcji daj膮cych w wyniku liczby ca艂kowite |
Przyk艂ad - funkcja zwracaj膮ca d艂ugo艣膰 tekstu
int d艂ugo艣膰 (t)
char *t;
{
int n;
for (n = 0; *t != '\0'; t++)
{++n;}
return n;
}
Wywo艂anie:
char *tekst="ola ma kota";
printf ("dlugo艣膰 tekstu = % d, d艂ugo艣膰(tekst));
聽
Argumenty funkcji main
W wielu systemach operacyjnych funkcja main akceptuje dwie zmienne:
- int argc - liczb臋 ca艂kowit膮 pokazuj膮c膮 liczb臋 argument贸w w wierszu polece艅 przy wywo艂ywaniu programu (艂膮cznie z nazw膮 programu),
- char *argv[ ] - wska藕nik do tablicy ci膮g贸w znakowych, zawieraj膮cych argumenty z wiersza polece艅; alternatywnie argv mo偶e by膰 zadeklarowany jako **argv, je艣li programi艣cie ta posta膰 bardziej odpowiada.
Przyk艂ad
Je艣li program zosta艂 wywo艂any z systemu operacyjnego za pomoc膮 nast臋puj膮cego wiersza polece艅:
program abc def 6
to argc wynosi 4, a argv jest tablic膮 4 znak贸w: arg[0] = "program" arg[1] = "abc" arg[2] = "def" arg[3] = "6"
Standardowa posta膰 programu do przegl膮dania argument贸w funkcji main (opr贸cz pierwszego, kt贸ry jest zawsze nazw膮 programu) ma posta膰:
main (argc, argv)
int argc;
char **argv;
{while (--argc > 0)
{ ... *( ++argv ) ... }}
聽 |
---|