Professional Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
Programowanie
w jzyku C. FAQ
Autor: Steve Summit
Tumaczenie: Przemysaw Kowalczyk
ISBN: 83-7361-094-4
Tytu oryginau: C Programming FAQs
Format: B5, stron: 400
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Przysowie kto pyta, nie bdzi nie zawiera caej prawdy. Nie wystarczy pyta, trzeba
jeszcze znajdowa odpowiedzi. Ksika Programowanie w jzyku C. FAQ to zbir
kilkuset odpowiedzi na najczciej zadawane pytania na temat tego jzyka
programowania. Z pewnoci cz z przedstawionych tu pyta ju pojawia si
w Twojej praktyce programistycznej (pamitasz, ile czasu stracie poszukujc
odpowiedzi?). Inne problemy dopiero si pojawi i jeli na Twojej pce bdzie ta
ksika, szybko znajdziesz w niej zwize, ale wyczerpujce rozwizanie czsto
wzbogacone przykadem kodu rdowego.
Chocia ksika adn miar nie powinna by traktowana jako podrcznik, z ktrego
mona nauczy si programowania w C, z pewnoci przyda si kadej osobie
uywajcej tego jzyka w codziennej praktyce. Autor porusza wiele przydatnych
zagadnie obejmujcych szeroki zestaw tematw.
Omwiono midzy innymi:
Deklaracje
Struktury i unie
Puste wskaniki
Wyraenia
Makroprocesor
Alokacj pamici
Rnice midzy standardami C
Standardow bibliotek wejcia-wyjcia
Kwestie zwizane z systemami operacyjnymi
Spis treci
Pytania.............................................................................................. 9
Przedmowa...................................................................................... 37
Wprowadzenie ................................................................................. 41
Jak korzysta z tej ksiki? ......................................................................................41
Format pyta..........................................................................................................43
Przykady kodu ......................................................................................................43
Organizacja ksiki .................................................................................................44
Rozdzia 3. Wyraenia........................................................................................ 89
Kolejno obliczania ...............................................................................................89
Inne pytania na temat wyrae.................................................................................96
Reguy zachowywania........................................................................................... 100
Spis treci
7
Otwieranie plikw i operacje na nich ...................................................................... 232
Przekierowywanie strumieni stdin i stdout............................................................... 235
Obsuga wejcia-wyjcia w trybie binarnym ............................................................ 237
Rozdzia 6.
Tablice i wskaniki
Sia jzyka C wynika midzy innymi z ujednoliconego traktowania tablic i wskanikw. Bardzo atwo jest za pomoc wskanikw operowa na tablicach czy symulowa tablice tworzone dynamicznie. Tak zwana odpowiednio wskanikw i tablic
jest tak dua, e niektrzy programici zapominaj o zasadniczych rnicach, mylc,
e s one identyczne, albo zakadajc nieistniejce midzy nimi podobiestwa.
Podstaw odpowiednioci tablic i wskanikw w jzyku C jest fakt, e odwoania
do tablic degeneruj si do wskanikw do pierwszego elementu tablicy, co opisuje
pytanie 6.3. Z tego powodu tablice s obywatelami drugiej kategorii w C nigdy
nie posugujesz si tablicami jako caymi obiektami (na przykad aby skopiowa je
albo przekaza do funkcji). Kiedy uyjesz nazwy tablicy, w wyraeniu pojawi si
wskanik zamiast caej tablicy. Nawet operator indeksowania tablic w rzeczywistoci operuje na wskaniku. Wyraenie jest rwnowane wyraeniu wskanikowemu .
Dua cz tego rozdziau (szczeglnie pytania retrospektywne 6.8 6.10) moe
wydawa si powtarzaniem wci tych samych wiadomoci. Wielu programistw ma
jednak spore kopoty ze zrozumieniem zwizkw i rnic midzy wskanikami i tablicami, w tym rozdziale staram si wyjani je najlepiej, jak tylko potrafi. Jeeli
nudz Ci takie powtrki, moesz przeskoczy do nastpnego rozdziau. Jeeli jednak
masz kopoty z tablicami lub wskanikami, przeczytaj uwanie odpowiedzi, a poszczeglne czci ukadanki na pewno wskocz na swoje miejsca.
128
Podstawowe zwizki
midzy tablicami i wskanikami
6.1
Pytanie: W jednym z plikw rdowych mam definicj , a w innym deklaracj
. Dlaczego to nie dziaa?
Odpowied: Zmienna zadeklarowana przy uyciu
nie jest typu tablicowego, nie pasuje wic do rzeczywistej definicji. Typ wskanik do typu nie jest
tym samym, co typ tablica elementw typu . Uyj deklaracji
.
Referencje: ANSI 3.5.4.2
ISO 6.5.4.2
CT&P 3.3, 4.5
6.2
Pytanie: Ale przecie syszaem, e i
to to samo. Czy to prawda?
Odpowied: Nie, to nie jest prawda (to, co syszae, odnosio si do parametrw formalnych funkcji, zobacz pytanie 6.4). Tablice nie s wskanikami, chocia s blisko
z nimi zwizane (zobacz pytanie 6.3) i korzysta si z nich podobnie (zobacz pytania
4.1, 6.8, 6.10 i 6.14).
Deklaracja tablicy powoduje przydzielenie miejsca na sze znakw i powizanie go z nazw . Innymi sowy, stanowi adres obszaru pamici, w ktrym
zmieci si sze znakw. Z drugiej strony, deklaracja wskanika powoduje
przydzielenie miejsca na wskanik i powizanie go z nazw . Wskanik ten moe
wskazywa praktycznie gdziekolwiek: na pojedyncz zmienn typu , na cig
tablic elementw typu albo nigdzie 1 (zobacz te pytania 1.30 i 5.1).
Jak zwykle w takich sytuacjach, obrazek wart jest tysica sw. Deklaracje:
Nie naley jednak interpretowa poj gdziekolwiek i nigdzie zbyt szeroko. Aby wskanik mia
poprawn warto, musi wskazywa na prawidowo przydzielony obszar pamici (zobacz pytania 7.1,
7.2 i 7.3). Aby wskazywa nigdzie, musi by wskanikiem pustym (zobacz pytanie 5.1).
129
6.3
Pytanie: Co w takim razie oznacza odpowiednio wskanikw i tablic w C?
Odpowied: Wiele nieporozumie dotyczcych tablic i wskanikw w jzyku C bierze
si wanie z niewaciwego rozumienia tego pojcia. Odpowiednio nie oznacza,
e s one identyczne, ani nawet, e mog by uywane wymiennie. Definicj owej
odpowiednioci mona przedstawi nastpujco: referencja do obiektu o typie tablica elementw typu , degeneruje si w wyraeniach (z trzema wyjtkami) do
wskanika do pierwszego elementu tablicy. Jest on typu wskanik do typu (Wspomniane wyjtki to: kiedy nazwa tablicy jest argumentem operatora , operatora
albo jest literaem napisowym w inicjalizatorze tablicy znakw 2. Zobacz pytania 6.23,
6.12 i 1.32, odpowiednio).
Z takiej definicji wynika, e zastosowanie operatora do tablic i wskanikw nie rni si tak bardzo 3, mimo e s to odmienne obiekty. Jeeli to tablica, a to wskanik, wyraenie w postaci powoduje, e odwoanie do tablicy zamieniane jest
niejawnie na wskanik do pierwszego elementu, zgodnie z powysz regu. Dalsze
operacje s identyczne jak w przypadku indeksowania wskanika w wyraeniu
(chocia obliczenie rni si operacjami odczytu pamici, jak wyjaniem w pytaniu
6.2). Jeeli przypiszesz do wskanika adres tablicy:
Za litera napisowy w inicjalizatorze tablicy znakw uwaamy take literay inicjalizujce tablice
znakw .
Mwic cile, operator zawsze jest stosowany do wskanikw, zobacz pytanie 6.10, punkt 2.
130
Dziki temu wanie wskaniki mona tak atwo stosowa do operacji na tablicach,
uywa ich zamiast tablic jako argumentw funkcji (zobacz pytanie 6.4) czy symulowa tablice dynamiczne (zobacz pytanie 6.14).
Zobacz te pytania 6.8 i 6.10.
Referencje: K&R1 5.3
K&R2 5.3
ANSI 3.2.2.1, 3.3.2.1, 3.3.6
ISO 6.2.2.1, 6.3.2.1, 6.3.6
H&S 5.4.1
6.4
Pytanie: Jeeli wic tablice i wskaniki rni si tak bardzo, dlaczego mona
uywa ich wymiennie jako parametrw formalnych funkcji?
Odpowied: Dla wygody.
Poniewa w wyraeniach tablice staj si wskanikami, do funkcji przekazywane s
zawsze wskaniki, a nigdy tablice. Moesz udawa, e funkcja oczekuje jako parametru tablicy i podkreli to w kodzie rdowym, deklarujc funkcj jako:
Jednak taka deklaracja, zinterpretowana dosownie, nie ma zastosowania, gdy funkcja i tak otrzyma wskanik, wic dla kompilatora rwnowana jest z deklaracj:
131
6.5
Pytanie: Czemu tablicom nie mona przypisywa wartoci? Poniszy kod nie dziaa:
!"#
Jeeli chcesz operowa na tablicach bez kopiowania ich zawartoci, moesz uywa
wskanikw wtedy wystarczy zwyke przypisanie. Zobacz te pytania 4.1 i 8.2.
Referencje: ANSI 3.2.2.1
ISO 6.2.2.1
H&S 7.9.1
6.6
Pytanie: Jeeli nie mog przypisywa wartoci tablicom, w jaki sposb dziaa ten
kod?
&
&'('
)$
132
6.7
Pytanie: W jaki sposb tablica moe by l-wartoci, jeeli nie mona do niej przypisa?
Odpowied: Termin l-warto nie oznacza w rzeczywistoci czego, czemu mona
przypisa warto. Lepsz definicj byoby co, co posiada adres w pamici4. Standard ANSI/ISO jzyka C definiuje rwnie pojcie modyfikowalnej l-wartoci. Tablica ni nie jest. Zobacz te pytanie 6.5.
Referencje: ANSI 3.2.2.1
ISO 6.2.2.1
Rationale 3.2.2.1
H&S 7.1
Retrospektywa
Poniewa zwizki midzy tablicami i wskanikami powoduj tyle nieporozumie, kilka nastpnych pyta dotyczy wanie przyczyn tych nieporozumie.
6.8
Pytanie: Jaka jest praktyczna rnica midzy tablicami i wskanikami?
Odpowied: Tablica jest pojedynczym, przydzielonym wczeniej cigym obszarem
pamici, zawierajcym elementy tego samego typu. Posiada stay rozmiar i pooenie.
Wskanik to odniesienie do dowolnego elementu (okrelonego typu) gdziekolwiek.
Wskanikowi naley przypisa adres przydzielonego w jaki sposb obszaru pamici,
ale mona jego warto modyfikowa (a obszarowi pamici, jeeli zosta przydzielony dynamicznie, mona zmieni rozmiar). Wskanik moe wskazywa na elementy
tablicy i mona go uy (wraz z funkcj ) do symulowania dynamicznych tablic. Wskaniki s jednak znacznie bardziej ogln struktur danych (zobacz rwnie
pytanie 4.1).
Z powodu tak zwanej odpowiednioci wskanikw i tablic (zobacz pytanie 6.3)
moe si wydawa, e tablic i wskanikw mona uywa wymiennie. Wskanik do
obszaru pamici przydzielonego przez funkcj jest czsto traktowany jako tablica (moe by nawet argumentem operatora ). Zobacz pytania 6.14 i 6.16 (Pamitaj o zachowaniu ostronoci przy uyciu operatora , zobacz pytanie 7.28).
Zobacz te pytania 1.32, 6.10 i 20.14.
4
133
6.9
Pytanie: Kto wyjani mi, e tablice to w rzeczywistoci stae wskaniki. Czy to
prawda?
Odpowied: To zbyt uproszczone wyjanienie. Nazwa tablicy jest sta w tym sensie, e nie mona jej przypisa wartoci. Jednak tablica to nie wskanik, co powinna
wyjani odpowied na pytanie 6.2. Zobacz te pytania 6.3, 6.8 i 6.10.
6.10
Pytanie: Cigle nie do koca rozumiem. Czy wskanik jest rodzajem tablicy, czy
moe tablica jest rodzajem wskanika?
Odpowied: Tablica nie jest wskanikiem, a wskanik nie jest tablic. Referencja do tablicy (czyli uycie nazwy tablicy w kontekcie wyraenia) jest zamieniana na wskanik
(zobacz pytania 6.2 i 6.3).
S przynajmniej trzy prawidowe interpretacje tej sytuacji:
1. Wskaniki mog symulowa tablice (ale to nie jedyne ich zastosowanie,
dziaajcym na wskaniku.
3. Na wyszym poziomie abstrakcji wskanik do cigego obszaru pamici moe
6.11
Pytanie: Spotkaem si z dowcipnym kodem, zawierajcym wyraenie .
Dlaczego jest ono poprawne?
Odpowied: Moe to zabrzmi niewiarygodnie, ale indeksowanie tablic jest dziaaniem przemiennym 5 w jzyku C. Ten ciekawy fakt wynika ze wskanikowej definicji
5
Przemienno dotyczy tylko argumentw operatora . Wyraenie &* jest w oczywisty sposb
rne od wyraenia *&.
134
operatora . Wyraenie jest rwnowane dla dowolnych dwch wyrae i , jeeli tylko jedno z nich jest wyraeniem wskanikowym, a drugie cakowitym. Dowd przemiennoci mgby wyglda tak:
jest z definicji rwnowane:
jest rwnowane na mocy przemiennoci dodawania:
jest z definicji rwnowane:
.
Nieoczekiwana przemienno operatora traktowana jest zazwyczaj w tekstach o jzyku C jako powd do dumy, chocia nie ma sensownych zastosowa poza Konkursami Zaciemnionego Kodu w C (zobacz pytanie 20.36).
Poniewa napisy w jzyku C s tablicami elementw typu , wyraenie !
" jest cakowicie poprawne. Jego wartoci jest litera . Moesz uwaa to za
skrcon posta wyraenia:
+ ,
+-
Wskaniki do tablic
Poniewa tablice zwykle zamieniane s na wskaniki, szczeglnie atwo o nieporozumienia, kiedy operujemy na wskanikach do caych tablic (zamiast, jak zwykle, do
ich pierwszych elementw).
6.12
Pytanie: Jeeli odwoania do tablic przeksztacane s na wskaniki, jaka jest rnica midzy i (przy zaoeniu, e to jaka tablica)?
Odpowied: Wyraenia te rni si typem.
Standard jzyka C stanowi, e wyraenie jest typu wskanik do tablicy elementw typu i zwraca wskanik do caej tablicy (wczeniejsze kompilatory generalnie ignoroway operator w takim kontekcie, czasem tylko zgaszajc ostrzeenie).
We wszystkich kompilatorach jzyka C odwoanie do nazwy tablicy (bez operatora )
zwraca wskanik, typu wskanik do typu , do pierwszego elementu tablicy.
135
odwoanie do jest typu wskanik do tablicy #$%&'(#) elementw typu
, natomiast wskanik do tablicy #*%+) tablic o #$%&'(#) elementw typu
.
Zobacz te pytania 6.3, 6.13 i 6.18.
Referencje: ANSI 3.2.2.1, 3.3.3.2
ISO 6.2.2.1, 6.3.3.2
Rationale 3.3.3.2
H&S 7.5.6
6.13
Pytanie: Jak zadeklarowa wskanik do tablicy?
Odpowied: Zastanw si, czy rzeczywicie go potrzebujesz. Kiedy kto mwi o wskaniku do tablicy, ma zazwyczaj na myli wskanik do jej pierwszego elementu.
Zamiast wskanika do tablicy czasem lepiej uy wskanika do jednego z elementw
tablicy. Tablice elementw typu staj si w wyraeniach wskanikami do typu
(zobacz pytanie 6.3), co jest bardzo wygodne. Indeksowanie albo zwikszanie powstaego tak wskanika pozwala na dostp do elementw tablicy. Rzeczywiste wskaniki do tablic, kiedy s indeksowane lub zwikszane, przechodz przez cae tablice
i s przydatne tylko, gdy operujemy na tablicach tablic6 (zobacz pytanie 6.18).
Jeeli naprawd potrzebujesz wskanika do caej tablicy, zadeklaruj go na przykad
tak:
#, gdzie # to rozmiar tablicy (zobacz te pytanie 1.21). Jeeli rozmiar
tablicy jest nieznany, # mona teoretycznie pomin, ale zadeklarowany w ten sposb
wskanik do tablicy nieznanego rozmiaru jest bezuyteczny.
Ponisze przykady pokazuj rnice midzy zwykymi wskanikami a wskanikami
do tablic. Przy zaoeniu, e obowizuj deklaracje:
&6%%7
&7766%8%-%9%:%;
&&
<=!&=$)&<
&6
<=!&=,&$6
+
>$)&<
136
spowodowaaby wypisanie 0 i zachowanie niezdefiniowane (od wypisania przypadkowej wartoci do bdu w czasie wykonania) w momencie drugiego wywoania funkcji
. Wskanik do tablicy moe si przyda, kiedy operujemy na tablicy tablic,
na przykad :
7
& ??( %%
@@
<D
D&+$E
*,&$<
& ??( %%
6.14
Pytanie: Jak okreli rozmiar tablicy w czasie dziaania programu? Jak unikn
tablic o z gry ustalonym rozmiarze?
Odpowied: Odpowiednio tablic i wskanikw (zobacz pytanie 6.3) pozwala symulowa tablice dynamiczne za pomoc wskanika do obszaru pamici, dostarczonego przez funkcj . Po wykonaniu:
137
F&)
G&,HI
&$$&+&D
&
(i jeeli wywoanie funkcji si powiedzie) moesz odwoywa si do !
(dla od 0 do 9) tak, jakby !
bya zwyk, statycznie utworzon tablic
(
,.). Zobacz rwnie pytania 6.16, 7.28 i 7.29.
6.15
Pytanie: Jak zadeklarowa lokaln tablic o rozmiarze rwnym tablicy przekazanej jako parametr?
Odpowied: W jzyku C nie mona tego zrobi. Rozmiary tablic musz by znane
w czasie kompilacji (Kompilator GNU C dopuszcza moliwo deklarowania tablic
o zmiennym rozmiarze jako rozszerzenie; znalazo si ono rwnie w standardzie
C99). Moesz uy funkcji , aby stworzy tablic dynamiczn, ale pamitaj o zwolnieniu jej funkcj . Zobacz te pytania 6.14, 6.16, 6.19, 7.22 i moe
rwnie 7.32.
Referencje: ANSI 3.4, 3.5.4.2
ISO 6.4, 6.5.4.2
6.16
Pytanie: Jak dynamicznie przydzieli pami dla tablicy wielowymiarowej?
Odpowied: W wikszoci przypadkw najlepiej stworzy tablic7 wskanikw do
wskanikw, a nastpnie kademu ze wskanikw przypisa adres dynamicznie przydzielonego wiersza. Oto przykad dla tablicy dwuwymiarowej:
F&)
G&,HI
&$&+&D
&
&
&G
&@@
$&&+)+&D
&
W rzeczywistym kodzie naleaoby oczywicie sprawdzi wszystkie wartoci zwrcone przez funkcj .
Jeeli nie zamierzasz zmienia dugoci wierszy, a za to chciaby, aby przydzielony
tablicy obszar pamici by cigy, wystarczy odrobina arytmetyki na wskanikach:
&$7&+&D
&
$7&+)+&D
&
&
&G
&@@
$7&$7@&)+
7
Mwic cile, nie s to tablice, ale raczej obiekty uywane jak tablice, zobacz pytanie 6.14.
138
W obu przypadkach (to znaczy tablic , i ) tablice dynamiczne mona indeksowa za pomoc normalnych operatorw: Z/ (dla .01#*%+) i .0
/1#$%&'(#)). Poniszy rysunek przedstawia schematycznie ukad wierszy w tablicach , i .
Jeeli dwa odwoania do pamici w tym schemacie s z jakich powodw nie do przyjcia8, moesz zasymulowa tablic dwuwymiarow dynamicznie stworzon tablic
jednowymiarow:
&$6&+)+&D
&
Zauwa jednak, e dwukrotne odwoanie do tablicy nie musi by wcale mniej efektywne ni jawne
mnoenie indeksw.
Jawne obliczanie indeksu mona ukry w makrodefinicji, na przykad: F
&
J$
%&%*
&)+@*. Jednak wywoanie takiej makrodefinicji, z nawiasami i przecinkami,
nie kojarzyoby si z normaln skadni dostpu do tablic. Makrodefinicja musiaaby mie rwnie
dostp do jednego z wymiarw tablicy.
139
albo nawet:
&$-./0 1.20345.1
&./0 1.20345.1+&D
$-
Jednak skadnia odwoania do elementw wskazywanych tablic robi si coraz bardziej skomplikowana (w przypadku " trzeba pisa "/). Najwyej
jeden wymiar tablicy mona okreli w czasie dziaania programu.
Uywajc tych technik, nie mona oczywicie zapomnie o zwolnieniu przydzielonej
pamici, kiedy nie jest ju potrzebna. W przypadku tablic , i wymaga to
kilku krokw (zobacz te pytanie 7.23):
&
&G
&@@
K&$&
K&$
K&$7
K&$7
Nie moesz te miesza tablic przydzielonych dynamicznie ze zwykymi, utworzonymi statycznie (zobacz pytanie 6.20, a take 6.18).
Powysze techniki mona oczywicie rozszerzy na trzy i wicej wymiarw. Oto trjwymiarowa wersja pierwszego sposobu:
&6&+&+&D
&
&
&G&+
&@@
6&&+$&+&D
&
*
*G$&+
*@@
6&*&+D&+&D
&
6.17
Pytanie: Wpadem na fajny pomys jeeli napisz:
&
$
&$A
$L
mog traktowa tablic tak, jakby jej indeksy zaczynay si od 1. Czy to
poprawne?
Odpowied: Chocia taka technika moe wydawa si atrakcyjna (bya nawet uywana w starszych wydaniach ksiki Numerical Recipes in C), nie jest zgodna ze Standardem jzyka C. Arytmetyka wskanikw zdefiniowana jest tylko, jeeli warto
wskanika pozostaje w obrbie tego samego przydzielonego bloku pamici albo
umownego kocowego elementu tu za nim. W przeciwnym wypadku zachowanie
programu jest niezdefiniowane, nawet jeeli nie nastpuje dereferencja wskanika.
Kod w pytaniu oblicza wskanik do obszaru przed pocztkiem tablicy .
140
W momencie odejmowania offsetu moe wystpi bd wygenerowania nieprawidowego adresu (na przykad gdyby obliczenie adresu spowodowao zawinicie wok
pocztku segmentu pamici).
Referencje: K&R2 5.3, 5.4, A7.7
ANSI 3.3.6
ISO 6.3.6
Rationale 3.2.2.3
6.18
Pytanie: Mj kompilator zgasza bdy, kiedy przekazuj tablic dwuwymiarow
do funkcji przyjmujcej wskanik do wskanika. Dlaczego?
Odpowied: Zasada (zobacz pytanie 6.3), na mocy ktrej tablice degeneruj si do
wskanikw, nie dziaa rekurencyjnie. Tablica dwuwymiarowa (czyli w jzyku C tablica tablic) staje si wskanikiem do tablicy, nie wskanikiem do wskanika. Wskaniki do tablic powoduj duo nieporozumie, dlatego naley ich uywa ostronie.
Zobacz pytanie 6.13 (nieporozumienia wzmaga fakt, e istniej kompilatory, w tym
stare wersje i oparte na nich wersje programu
, ktre niepoprawnie pozwalaj
przypisywa wielowymiarowe tablice do wskanikw na wskaniki).
Jeeli przekazujesz dwuwymiarow tablic do funkcji:
&$./0 1.20345.1
$
albo:
&.20345.1<=!&=,&E<
141
&&
&&A$
A&
<MNO50PCB3C<
Taki sposb wywoania jest jednak mylcy i prawie na pewno nieprawidowy. Tablica zostaa spaszczona stracilimy informacj o jej szerokoci.
Zobacz te pytania 6.12 i 6.15.
Referencje: K&R1 5.10
K&R2 5.9
H&S 5.4.3
6.19
Pytanie: Jak tworzy funkcje, ktre przyjmuj tablice dwuwymiarowe, jeeli nie
znam ich szerokoci w czasie kompilacji?
Odpowied: To nie jest atwe. Jednym ze sposobw jest przekazanie wskanika do
elementu o indeksach .. wraz z obydwoma wymiarami i rczne obliczanie indeksw:
7&$%&%&)+
$&)+@*<"&
+
)$&*<
142
6.20
Pytanie: Jak korzysta jednoczenie z wielowymiarowych tablic przydzielanych
statycznie i dynamicznie przy przekazywaniu ich do funkcji?
Odpowied: Nie ma jednej, uniwersalnej metody. Majc deklaracje:
&$./0 1.20345.1
&$
<=Q$&
D,<
&$7
<&R"$,D+&E&<
&$6
<,& "DD <
&$8.20345.1
&$-./0 1.20345.1
gdzie funkcja , akceptuje zwyk tablic dwuwymiarow, funkcja spaszczon tablic dwuwymiarow, a funkcja tablic symulowan przez wskanik
do wskanika (zobacz pytania 6.18 i 6.19), ponisze wywoania funkcji dziaaj
zgodnie z oczekiwaniami:
$%./0 1%.20345.1
$8%%.20345.1
$-%./0 1%.20345.1
7A$%./0 1%.20345.1
7$%./0 1%.20345.1
7$7%%)+
7$6%%)+
7$8%%.20345.1
7$-%./0 1%.20345.1
6$%%)+
6$7%%)+
143
Z wyej wymienionych tylko funkcja moe przyjmowa tablice statyczne i przydzielone dynamicznie, chocia nie bdzie dziaa dla tradycyjnej implementacji ,,
czyli kady wiersz osobno. Pamitaj jednak, e przekazywanie .. (albo
) do funkcji nie jest cile zgodne ze Standardem zobacz pytanie 6.19.
Jeeli rozumiesz, dlaczego wszystkie wyej wymienione sposoby przekazywania tablic
wielowymiarowych do funkcji dziaaj oraz dlaczego kombinacje, ktrych tu nie przedstawiono, nie dziaaj, moesz uzna, e bardzo dobrze rozumiesz tablice i wskaniki
w jzyku C.
Zamiast jednak zaprzta sobie gow tymi wszystkimi trudnymi reguami, moesz
zastosowa duo prostsze rozwizanie: wszystkie tablice wielowymiarowe twrz dynamicznie, jak w pytaniu 6.16. Jeeli nie bdzie statycznych tablic wielowymiarowych wszystkie bd przydzielane jak , lub w pytaniu 6.16 wtedy
wszystkie funkcje mog mie deklaracje podobne do .
Rozmiary tablic
Operator zwraca rozmiar tablicy, ale tylko wtedy, gdy jest on znany, a odniesienie do tablicy nie zredukowao si do wskanika.
6.21
Pytanie: Dlaczego operator nie zwraca poprawnego rozmiaru tablicy, ktra
jest parametrem funkcji? Moja testowa funkcja wypisuje 4, zamiast 10:
&&&D
& ?( %&
Odpowied: Kompilator podmienia typ parametru z tablicy na wskanik (w tym przypadku , zobacz pytanie 6.4). Operator zwraca w tym wypadku rozmiar
wskanika. Zobacz te pytania 1.24 i 7.28.
Referencje: H&S 7.5.2
144
6.22
Pytanie: Jak kod w pliku, w ktrym tablica zadeklarowana jest jako
(jest
zdefiniowana i jej rozmiar jest okrelony w innym pliku), moe okreli jej wielko? Operator nie dziaa na niej.
Odpowied: Zobacz pytanie 1.24.
6.23
Pytanie: Jak mog okreli liczb elementw tablicy, jeeli operator zwraca
rozmiar w bajtach?
Odpowied: Po prostu podziel rozmiar caej tablicy przez rozmiar jednego elementu:
&$%7%6
&$&D
$<&D
$
Referencje: ANSI 3.3.3.4
ISO 6.3.3.4