Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00522 007502 11067185 na godz. na dobę w sumie
Programowanie w języku C. FAQ - książka
Programowanie w języku C. FAQ - książka
Autor: Liczba stron: 400
Wydawca: Helion Język publikacji: polski
ISBN: 83-7361-094-4 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> c - programowanie
Porównaj ceny (książka, ebook, audiobook).
Przysłowie 'kto pyta, nie błądzi' nie zawiera całej prawdy. Nie wystarczy pytać, trzeba jeszcze znajdować odpowiedzi. Książka 'Programowanie w języku C. FAQ' to zbiór kilkuset odpowiedzi na najczęściej zadawane pytania na temat tego języka programowania. Z pewnością część z przedstawionych tu pytań już pojawiła się w Twojej praktyce programistycznej (pamiętasz, ile czasu straciłeś poszukując odpowiedzi?). Inne problemy dopiero się pojawią i jeśli na Twojej półce będzie ta książka, szybko znajdziesz w niej zwięzłe, ale wyczerpujące rozwiązanie często wzbogacone przykładem kodu źródłowego.

Chociaż książka żadną miarą nie powinna być traktowana jako podręcznik, z którego można nauczyć się programowania w C, z pewnością przyda się każdej osobie używającej tego języka w codziennej praktyce. Autor porusza wiele przydatnych zagadnień obejmujących szeroki zestaw tematów.

Omówiono między innymi:

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

IDZ DO IDZ DO PRZYK£ADOWY ROZDZIA£ PRZYK£ADOWY ROZDZIA£ SPIS TREĎCI SPIS TREĎCI KATALOG KSI¥¯EK KATALOG KSI¥¯EK KATALOG ONLINE KATALOG ONLINE ZAMÓW DRUKOWANY KATALOG ZAMÓW DRUKOWANY KATALOG TWÓJ KOSZYK TWÓJ KOSZYK DODAJ DO KOSZYKA DODAJ DO KOSZYKA CENNIK I INFORMACJE CENNIK I INFORMACJE ZAMÓW INFORMACJE ZAMÓW INFORMACJE O NOWOĎCIACH O NOWOĎCIACH ZAMÓW CENNIK ZAMÓW CENNIK CZYTELNIA CZYTELNIA Programowanie w jêzyku C. FAQ Autor: Steve Summit T³umaczenie: Przemys³aw Kowalczyk ISBN: 83-7361-094-4 Tytu³ orygina³u: C Programming FAQs Format: B5, stron: 400 Przys³owie „kto pyta, nie b³¹dzi” nie zawiera ca³ej prawdy. Nie wystarczy pytaæ, trzeba jeszcze znajdowaæ odpowiedzi. Ksi¹¿ka „Programowanie w jêzyku C. FAQ” to zbiór kilkuset odpowiedzi na najczêġciej zadawane pytania na temat tego jêzyka programowania. Z pewnoġci¹ czêġæ z przedstawionych tu pytañ ju¿ pojawi³a siê w Twojej praktyce programistycznej (pamiêtasz, ile czasu straci³eġ poszukuj¹c odpowiedzi?). Inne problemy dopiero siê pojawi¹ i jeġli na Twojej pó³ce bêdzie ta ksi¹¿ka, szybko znajdziesz w niej zwiêz³e, ale wyczerpuj¹ce rozwi¹zanie czêsto wzbogacone przyk³adem kodu ĥród³owego. Chocia¿ ksi¹¿ka ¿adn¹ miar¹ nie powinna byæ traktowana jako podrêcznik, z którego mo¿na nauczyæ siê programowania w C, z pewnoġci¹ przyda siê ka¿dej osobie u¿ywaj¹cej tego jêzyka w codziennej praktyce. Autor porusza wiele przydatnych zagadnieñ obejmuj¹cych szeroki zestaw tematów. FRAGMENTY KSI¥¯EK ONLINE FRAGMENTY KSI¥¯EK ONLINE Omówiono miêdzy innymi: • Deklaracje • Struktury i unie • Puste wskaĥniki • Wyra¿enia • Makroprocesor • Alokacjê pamiêci • Ró¿nice miêdzy standardami C • Standardow¹ bibliotekê wejġcia-wyjġcia • Kwestie zwi¹zane z systemami operacyjnymi Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl Spis treści Pytania............................................z.................................................. 9 Przedmowa ...................................................z................................... 37 Wprowadzenie ...................................................z.............................. 41 Jak korzystać z tej książki? ...................................................t...................................41 Format pytań...................................................t...................................................t....43 Przykłady kodu ...................................................t...................................................t43 Organizacja książki ...................................................t..............................................44 Rozdział 1. Deklaracje i inicjalizacja...................................................z................ 47 Podstawowe typy...................................................t.................................................47 Deklaracje wskaźników ...................................................t........................................50 Styl deklaracji...................................................t...................................................t...51 Klasy pamięci...................................................t...................................................t...54 Definicje typów ...................................................t...................................................t55 Kwalifikator const ...................................................t...............................................59 Złożone deklaracje ...................................................t...............................................59 Rozmiary tablic ...................................................t...................................................t62 Problemy z deklaracjami ...................................................t......................................64 Przestrzeń nazw...................................................t...................................................t65 Inicjalizacja...................................................t...................................................t......69 Rozdział 2. Struktury, unie i typy wyliczeniowe...................................................z 73 Deklaracje struktur...................................................t...............................................73 Działania na strukturach...................................................t.......................................78 Wyrównywanie pól struktur...................................................t..................................80 Dostęp do pól struktur...................................................t..........................................82 Różne pytania na temat struktur...................................................t............................83 Unie ...................................................t...................................................t................84 Typy wyliczeniowe ...................................................t..............................................85 Pola bitowe ...................................................t...................................................t......86 Rozdział 3. Wyrażenia..........................................z.............................................. 89 Kolejność obliczania ...................................................t............................................89 Inne pytania na temat wyrażeń...................................................t..............................96 Reguły zachowywania...................................................t........................................100 6 Programowanie w języku C. FAQ Rozdział 4. Wskaźniki ...................................................z................................... 103 Podstawy...................................................t...................................................t.......103 Działania na wskaźnikach...................................................t...................................105 Wskaźniki jako parametry funkcji ...................................................t.......................106 Różne zastosowania wskaźników ...................................................t........................110 Rozdział 5. Wskaźniki puste ...................................................z......................... 113 Wskaźniki puste i literały wskaźnika pustego ...................................................t.......113 Makrodefinicja NULL...................................................t........................................116 Retrospektywa...................................................t...................................................t121 Co można znaleźć pod adresem 0? ...................................................t......................124 Rozdział 6. Tablice i wskaźniki...................................................z...................... 127 Podstawowe związki między tablicami i wskaźnikami..............................................128 Tablicom nie można przypisywać wartości...................................................t...........131 Retrospektywa...................................................t...................................................t132 Wskaźniki do tablic...................................................t............................................134 Dynamiczne tworzenie tablic ...................................................t..............................136 Funkcje a tablice wielowymiarowe ...................................................t......................140 Rozmiary tablic ...................................................t.................................................143 Rozdział 7. Przydzielanie pamięci ...................................................z.................. 145 Podstawowe problemy z przydzielaniem pamięci...................................................t..145 Wywoływanie funkcji malloc...................................................t..............................149 Problemy z funkcją malloc...................................................t..................................152 Zwalnianie pamięci ...................................................t............................................155 Rozmiar przydzielonych bloków ...................................................t.........................158 Inne funkcje przydzielające pamięć ...................................................t.....................159 Rozdział 8. Znaki i napisy ...................................................z............................. 165 Rozdział 9. Wyrażenia i zmienne logiczne ...................................................z...... 171 Rozdział 10. Preprocesor języka C ...................................................z.................. 175 Makrodefinicje ...................................................t..................................................175 Pliki nagłówkowe ...................................................t..............................................180 Kompilacja warunkowa...................................................t......................................183 Zaawansowane przetwarzanie ...................................................t.............................186 Makrodefinicje ze zmienną liczbą argumentów...................................................t.....189 Rozdział 11. Standard ANSI/ISO języka C ...................................................z....... 193 Standard ...................................................t...................................................t........193 Prototypy funkcji ...................................................t...............................................195 Kwalifikator const ...................................................t.............................................198 Funkcja main...................................................t...................................................t..200 Właściwości preprocesora ...................................................t..................................203 Inne sprawy związane ze Standardem ANSI...................................................t.........205 Stare lub niezgodne ze Standardem kompilatory ...................................................t...208 Kwestie zgodności ...................................................t.............................................211 Rozdział 12. Standardowa biblioteka wejścia-wyjścia ......................................... 215 Podstawy obsługi wejścia-wyjścia ...................................................t.......................216 Formaty dla funkcji printf...................................................t...................................218 Formaty dla funkcji scanf ...................................................t...................................222 Problemy z funkcją scanf ...................................................t...................................224 Inne funkcje z biblioteki wejścia-wyjścia ...................................................t.............228 Spis treści 7 Otwieranie plików i operacje na nich...................................................t...................232 Przekierowywanie strumieni stdin i stdout..................................................t.............235 Obsługa wejścia-wyjścia w trybie binarnym...................................................t.........237 Rozdział 13. Funkcje biblioteczne ...................................................z................... 241 Funkcje operujące na napisach...................................................t............................241 Sortowanie ...................................................t...................................................t.....247 Data i czas ...................................................t...................................................t.....251 Liczby losowe ...................................................t...................................................t254 Inne funkcje biblioteczne...................................................t....................................261 Rozdział 14. Liczby zmiennoprzecinkowe ...................................................z......... 265 Rozdział 15. Listy argumentów o zmiennej długości............................................ 273 Wywoływanie funkcji o zmiennej liczbie argumentów .............................................274 Implementacja funkcji o zmiennej liczbie argumentów.............................................275 Pobieranie argumentów z listy...................................................t.............................280 Trudniejsze problemy...................................................t.........................................283 Rozdział 16. Dziwne problemy...................................................z......................... 287 Rozdział 17. Styl ...................................................z............................................ 293 Rozdział 18. Narzędzia i zasoby..............................................z............................ 299 Narzędzia...................................................t...................................................t.......299 Program lint ...................................................t...................................................t...301 Zasoby...................................................t...................................................t...........303 Rozdział 19. Kwestie zależne od systemu operacyjnego...................................... 309 Klawiatura i ekran...................................................t..............................................310 Inne operacje wejścia-wyjścia ...................................................t.............................316 Pliki i katalogi ...................................................t...................................................t318 Bezpośredni dostęp do pamięci ...................................................t...........................324 Polecenia systemowe ...................................................t.........................................326 Środowisko procesu...................................................t...........................................329 Inne operacje zależne od systemu...................................................t........................330 Retrospektywa...................................................t...................................................t333 Rozdział 20. Różności.............................................z........................................... 335 Przydatne techniki...................................................t..............................................336 Bity i bajty...................................................t...................................................t.....343 Wydajność ...................................................t...................................................t.....348 Instrukcja switch...................................................t................................................352 Różne kwestie językowe ...................................................t....................................354 Inne języki ...................................................t...................................................t.....358 Algorytmy...................................................t...................................................t......359 Inne...................................................t...................................................t...............364 Słownik ...................................................z...................................... 369 Bibliografia ...................................................z................................. 379 Skorowidz ...................................................z.................................. 383 Rozdział 6. Tablice i wskaźniki Siła języka C wynika między innymi z ujednoliconego traktowania tablic i wskaźni- ków. Bardzo łatwo jest za pomocą wskaźników operować na tablicach czy symulo- wać tablice tworzone dynamicznie. Tak zwana odpowiedniość wskaźników i tablic jest tak duża, że niektórzy programiści zapominają o zasadniczych różnicach, myśląc, że są one identyczne, albo zakładając nieistniejące między nimi podobieństwa. Podstawą „odpowiedniości” tablic i wskaźników w języku C jest fakt, że odwołania do tablic „degenerują się” do wskaźników do pierwszego elementu tablicy, co opisuje pytanie 6.3. Z tego powodu tablice są „obywatelami drugiej kategorii” w C — nigdy nie posługujesz się tablicami jako całymi obiektami (na przykład aby skopiować je albo przekazać do funkcji). Kiedy użyjesz nazwy tablicy, w wyrażeniu pojawi się wskaźnik zamiast całej tablicy. Nawet operator indeksowania tablic =? w rzeczywi- stości operuje na wskaźniku. Wyrażenie C=K? jest równoważne wyrażeniu wskaźni- kowemu C K . Duża część tego rozdziału (szczególnie pytania „retrospektywne” 6.8 – 6.10) może wydawać się powtarzaniem wciąż tych samych wiadomości. Wielu programistów ma jednak spore kłopoty ze zrozumieniem związków i różnic między wskaźnikami i ta- blicami, w tym rozdziale staram się wyjaśnić je najlepiej, jak tylko potrafię. Jeżeli nudzą Cię takie powtórki, możesz przeskoczyć do następnego rozdziału. Jeżeli jednak masz kłopoty z tablicami lub wskaźnikami, przeczytaj uważnie odpowiedzi, a po- szczególne części układanki na pewno „wskoczą na swoje miejsca”. 128 Programowanie w języku C. FAQ Podstawowe związki między tablicami i wskaźnikami 6.1 Pytanie: W jednym z plików źródłowych mam definicję EJCTC=?, a w innym de- klarację GZVGTPEJCT C. Dlaczego to nie działa? Odpowiedź: Zmienna zadeklarowana przy użyciu GZVGTPEJCT C nie jest typu tabli- cowego, nie pasuje więc do rzeczywistej definicji. Typ „wskaźnik do typu 6” nie jest tym samym, co typ „tablica elementów typu 6”. Użyj deklaracji GZVGTPEJCTC=?. Referencje: ANSI §3.5.4.2 ISO §6.5.4.2 CT P §3.3, §4.5 6.2 Pytanie: Ale przecież słyszałem, że EJCTC=? i EJCT C to to samo. Czy to prawda? Odpowiedź: Nie, to nie jest prawda (to, co słyszałeś, odnosiło się do parametrów for- malnych funkcji, zobacz pytanie 6.4). Tablice nie są wskaźnikami, chociaż są blisko z nimi związane (zobacz pytanie 6.3) i korzysta się z nich podobnie (zobacz pytania 4.1, 6.8, 6.10 i 6.14). Deklaracja tablicy EJCTC=? powoduje przydzielenie miejsca na sześć znaków i po- wiązanie go z nazwą C. Innymi słowy, C stanowi adres obszaru pamięci, w którym zmieści się sześć znaków. Z drugiej strony, deklaracja wskaźnika EJCT R powoduje przydzielenie miejsca na wskaźnik i powiązanie go z nazwą R. Wskaźnik ten może wskazywać praktycznie gdziekolwiek: na pojedynczą zmienną typu EJCT, na ciągłą tablicę elementów typu EJCT albo nigdzie 1 (zobacz też pytania 1.30 i 5.1). Jak zwykle w takich sytuacjach, obrazek wart jest tysiąca słów. Deklaracje: EJCTC=?JGNNQ EJCT RYQTNF powodują utworzenie i zainicjalizowanie struktur danych, które można zobrazować następująco: k 1 Nie należy jednak interpretować pojęć „gdziekolwiek” i „nigdzie” zbyt szeroko. Aby wskaźnik miał poprawną wartość, musi wskazywać na prawidłowo przydzielony obszar pamięci (zobacz pytania 7.1, 7.2 i 7.3). Aby wskazywać „nigdzie”, musi być wskaźnikiem pustym (zobacz pytanie 5.1). Rozdział 6. ♦ Tablice i wskaźniki 129 Należy pamiętać, że wyrażenie Z=? tłumaczone jest przez kompilator odmiennie, w zależności od tego, czy Z to wskaźnik, czy tablica. W zasięgu widoczności powyż- szych deklaracji wyrażenie C=? powoduje wygenerowanie następującego kodu: „weź adres tablicy C, dodaj do niego 3 i pobierz znak stamtąd”. Z kolei wyrażenie R=? tłu- maczone jest jako: „weź adres wskaźnika R, pobierz jego wartość, dodaj do niej 3 i pobierz znak stamtąd”. Innymi słowy, wyrażenie C=? odnosi się do znaku odległego o 3 miejsca od początku obiektu o nazwie C, natomiast R=? to znak odległy o 3 miejsca od obiektu wskazywanego przez R. W naszym przykładzie zarówno C=?, jak i R=? odnoszą się do litery N , ale nie są to te same litery i ich adresy obliczane są inaczej. Referencje: K R2 §5.5 CT P §4.5 6.3 Pytanie: Co w takim razie oznacza „odpowiedniość wskaźników i tablic” w C? Odpowiedź: Wiele nieporozumień dotyczących tablic i wskaźników w języku C bierze się właśnie z niewłaściwego rozumienia tego pojęcia. „Odpowiedniość” nie oznacza, że są one identyczne, ani nawet, że mogą być używane wymiennie. Definicję owej „odpowiedniości” można przedstawić następująco: referencja do obiektu o typie „ta- blica elementów typu 6”, „degeneruje się” w wyrażeniach (z trzema wyjątkami) do wskaźnika do pierwszego elementu tablicy. Jest on typu „wskaźnik do typu 6” (Wspo- mniane wyjątki to: kiedy nazwa tablicy jest argumentem operatora UKGQH, operatora  albo jest literałem napisowym w inicjalizatorze tablicy znaków 2. Zobacz pytania 6.23, 6.12 i 1.32, odpowiednio). Z takiej definicji wynika, że zastosowanie operatora =? do tablic i wskaźników nie róż- ni się tak bardzo 3, mimo że są to odmienne obiekty. Jeżeli C to tablica, a R to wskaź- nik, wyrażenie w postaci C=K? powoduje, że odwołanie do tablicy zamieniane jest niejawnie na wskaźnik do pierwszego elementu, zgodnie z powyższą regułą. Dalsze operacje są identyczne jak w przypadku indeksowania wskaźnika w wyrażeniu R=K? (chociaż obliczenie różni się operacjami odczytu pamięci, jak wyjaśniłem w pytaniu 6.2). Jeżeli przypiszesz do wskaźnika adres tablicy: RC to wyrażenia R=? i C=? będą się odnosić do tego samego elementu. k 2 3 Za „literał napisowy w inicjalizatorze tablicy znaków” uważamy także literały inicjalizujące tablice znaków YEJCTAV. Mówiąc ściśle, operator =? zawsze jest stosowany do wskaźników, zobacz pytanie 6.10, punkt 2. 130 Programowanie w języku C. FAQ Dzięki temu właśnie wskaźniki można tak łatwo stosować do operacji na tablicach, używać ich zamiast tablic jako argumentów funkcji (zobacz pytanie 6.4) czy symulo- wać 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: Jeżeli więc tablice i wskaźniki różnią się tak bardzo, dlaczego można używać ich wymiennie jako parametrów formalnych funkcji? Odpowiedź: Dla wygody. Ponieważ w wyrażeniach tablice stają się wskaźnikami, do funkcji przekazywane są zawsze wskaźniki, a nigdy tablice. Możesz „udawać”, że funkcja oczekuje jako para- metru tablicy i podkreślić to w kodzie źródłowym, deklarując funkcję jako: H EJCTC=? ]ŗ_ Jednak taka deklaracja, zinterpretowana dosłownie, nie ma zastosowania, gdyż funk- cja i tak otrzyma wskaźnik, więc dla kompilatora równoważna jest z deklaracją: H EJCT C ]ŗ_ Nie ma nic niewłaściwego w mówieniu, że funkcja otrzymuje jako parametr tablicę, jeżeli jest on wewnątrz funkcji traktowany jako tablica. Wymienne stosowanie tablic i wskaźników dopuszczalne jest jedynie w deklaracjach parametrów formalnych funkcji i w żadnym innym przypadku. Jeżeli podmiana tablicy na wskaźnik w deklaracji funkcji przeszkadza Ci, deklaruj parametry jako wskaźniki. Wiele osób uważa, że zamieszanie, jakie powodują takie deklaracje, znacznie przewa- ża nad korzyściami z faktu, że parametr „wygląda”, jakby był tablicą (Zauważ rów- nież, że taka konwersja zachodzi tylko raz; parametr typu EJCT C=?=? jest nieprawi- dłowy. Zobacz pytania 6.18 i 6.19). Zobacz też pytanie 6.21. Referencje: K R1 §5.3, §A10.1 K R2 §5.3, §A8.6.3, §A10.1 ANSI §3.5.4.3, §3.7.1, §3.9.6 ISO §6.5.4.3, §6.7.1, §6.9.6 H S §9.3 CT P §3.3 Ritchie, The Development of the C Language Rozdział 6. ♦ Tablice i wskaźniki 131 Tablicom nie można przypisywać wartości Jeżeli tablica pojawia się po prawej stronie operatora przypisania, kopiowany jest wskaźnik do pierwszego elementu, a nie cała tablica. Co więcej, tablica nie może się pojawić po lewej stronie operatora przypisania (między innymi dlatego, że i tak nie można jej przypisać całej tablicy, jak wynika z poprzedniego zdania). 6.5 Pytanie: Czemu tablicom nie można przypisywać wartości? Poniższy kod nie działa: GZVGTPEJCT IGVRCUU  EJCTUVT=? UVTIGVRCUU 9RTQYCFļJCUđQ  Odpowiedź: Tablice są „obywatelami drugiej kategorii” w języku C. Nie można im, między innymi, przypisywać wartości (zobacz też pytanie 6.7). Kiedy chcesz skopio- wać elementy z jednej tablicy do drugiej, musisz to wyrazić jawnie. W przypadku na- pisów, pamiętanych jako EJCT=?, odpowiednia jest najczęściej funkcja UVTER[: UVTER[ UVTIGVRCUU 9RTQYCFļJCUđQ  Jeżeli chcesz operować na tablicach bez kopiowania ich zawartości, możesz używać wskaźników — wtedy wystarczy zwykłe 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: Jeżeli nie mogę przypisywać wartości tablicom, w jaki sposób działa ten kod? KPVH EJCTUVT=? ] KH UVT=?  UVTRWUV[ ŗ _ Odpowiedź: W tym przypadku UVT jest parametrem funkcji. Jego deklaracja jest „podmieniana” przez kompilator, jak opisałem to w pytaniu 6.4. Innymi słowy, UVT jest wskaźnikiem (typu EJCT ), można więc mu przypisać wartość. 132 6.7 Programowanie w języku C. FAQ Pytanie: W jaki sposób tablica może być l-wartością, jeżeli nie można do niej przy- pisać? Odpowiedź: Termin l-wartość nie oznacza w rzeczywistości „czegoś, czemu można przypisać wartość”. Lepszą definicją byłoby „coś, co posiada adres w pamięci”4. Stan- dard ANSI/ISO języka C definiuje również pojęcie „modyfikowalnej l-wartości”. Ta- blica 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ż związki między tablicami i wskaźnikami powodują tyle nieporozumień, kil- ka następnych pytań dotyczy właśnie przyczyn tych nieporozumień. 6.8 Pytanie: Jaka jest praktyczna różnica między tablicami i wskaźnikami? Odpowiedź: Tablica jest pojedynczym, przydzielonym wcześniej ciągłym obszarem pamięci, zawierającym elementy tego samego typu. Posiada stały rozmiar i położenie. Wskaźnik to odniesienie do dowolnego elementu (określonego typu) gdziekolwiek. Wskaźnikowi należy przypisać adres przydzielonego w jakiś sposób obszaru pamięci, ale można jego wartość modyfikować (a obszarowi pamięci, jeżeli został przydzielo- ny dynamicznie, można zmienić rozmiar). Wskaźnik może wskazywać na elementy tablicy i można go użyć (wraz z funkcją OCNNQE) do symulowania dynamicznych ta- blic. Wskaźniki są jednak znacznie bardziej ogólną strukturą danych (zobacz również pytanie 4.1). Z powodu tak zwanej „odpowiedniości wskaźników i tablic” (zobacz pytanie 6.3) może się wydawać, że tablic i wskaźników można używać wymiennie. Wskaźnik do obszaru pamięci przydzielonego przez funkcję OCNNQE jest często traktowany jako ta- blica (może być nawet argumentem operatora =?). Zobacz pytania 6.14 i 6.16 (Pa- miętaj o zachowaniu ostrożności przy użyciu operatora UKGQH, zobacz pytanie 7.28). Zobacz też pytania 1.32, 6.10 i 20.14. k 4 Pierwotna definicja l-wartości rzeczywiście mówiła o lewej stronie operatora przypisania. Rozdział 6. ♦ Tablice i wskaźniki 133 6.9 Pytanie: Ktoś wyjaśnił mi, że tablice to w rzeczywistości stałe wskaźniki. Czy to prawda? Odpowiedź: To zbyt uproszczone wyjaśnienie. Nazwa tablicy jest „stałą” w tym sen- sie, że nie można jej przypisać wartości. Jednak tablica to nie wskaźnik, co powinna wyjaśnić odpowiedź na pytanie 6.2. Zobacz też pytania 6.3, 6.8 i 6.10. 6.10 Pytanie: Ciągle nie do końca rozumiem. Czy wskaźnik jest rodzajem tablicy, czy może tablica jest rodzajem wskaźnika? Odpowiedź: Tablica nie jest wskaźnikiem, a wskaźnik nie jest tablicą. Referencja do ta- blicy (czyli użycie nazwy tablicy w kontekście wyrażenia) jest zamieniana na wskaźnik (zobacz pytania 6.2 i 6.3). Są przynajmniej trzy prawidłowe interpretacje tej sytuacji: 1. Wskaźniki mogą symulować tablice (ale to nie jedyne ich zastosowanie, zobacz pytanie 4.1). 2. W języku C w zasadzie nie ma tablic z prawdziwego zdarzenia (są „obywatelami drugiej kategorii”). Nawet operator =? jest w rzeczywistości operatorem działającym na wskaźniku. 3. Na wyższym poziomie abstrakcji wskaźnik do ciągłego obszaru pamięci może być uważany za tablicę (chociaż są też inne zastosowania wskaźników). Z drugiej strony, nie należy myśleć w ten sposób: 4. „Są dokładnie takie same” (nieprawda, zobacz pytanie 6.2). 5. „Tablice to stałe wskaźniki” (nieprawda, zobacz pytanie 6.9). Zobacz też pytanie 6.8. 6.11 Pytanie: Spotkałem się z „dowcipnym” kodem, zawierającym wyrażenie =CDEFGH?. Dlaczego jest ono poprawne? Odpowiedź: Może to zabrzmi niewiarygodnie, ale indeksowanie tablic jest działa- niem przemiennym 5 w języku C. Ten ciekawy fakt wynika ze wskaźnikowej definicji k 5 Przemienność dotyczy tylko argumentów operatora =?. Wyrażenie C=K?=L? jest w oczywisty sposób różne od wyrażenia C=L?=K?. 134 Programowanie w języku C. FAQ operatora =?. Wyrażenie C=G? jest równoważne C G dla dowolnych dwóch wy- rażeń C i G, jeżeli tylko jedno z nich jest wyrażeniem wskaźnikowym, a drugie całko- witym. „Dowód” przemienności mógłby wyglądać tak:     C=G? jest z definicji równoważne: C   G jest równoważne na mocy przemienności dodawania: G   C jest z definicji równoważne: G=C?. Nieoczekiwana przemienność operatora =? traktowana jest zazwyczaj w tekstach o ję- zyku C jako powód do dumy, chociaż nie ma sensownych zastosowań poza Konkur- sami Zaciemnionego Kodu w C (zobacz pytanie 20.36). Ponieważ napisy w języku C są tablicami elementów typu EJCT, wyrażenie CDEF GH=? jest całkowicie poprawne. Jego wartością jest litera H . Możesz uważać to za skróconą postać wyrażenia: EJCT VORRVTCDEFGH ŗVORRVT=?ŗ W pytaniu 20.10 znajdziesz bardziej realistyczny przykład. Referencje: Rationale §3.3.2.1 H S §5.4.1, §7.4.1 Wskaźniki do tablic Ponieważ tablice zwykle zamieniane są na wskaźniki, szczególnie łatwo o nieporo- zumienia, kiedy operujemy na wskaźnikach do całych tablic (zamiast, jak zwykle, do ich pierwszych elementów). 6.12 Pytanie: Jeżeli odwołania do tablic przekształcane są na wskaźniki, jaka jest róż- nica między CTTC[ i CTTC[ (przy założeniu, że CTTC[ to jakaś tablica)? Odpowiedź: Wyrażenia te różnią się typem. Standard języka C stanowi, że wyrażenie CTTC[ jest typu „wskaźnik do tablicy ele- mentów typu 6” i zwraca wskaźnik do całej tablicy (wcześniejsze kompilatory gene- ralnie ignorowały operator  w takim kontekście, czasem tylko zgłaszając ostrzeżenie). We wszystkich kompilatorach języka C odwołanie do nazwy tablicy (bez operatora ) zwraca wskaźnik, typu „wskaźnik do typu 6”, do pierwszego elementu tablicy. Rozdział 6. ♦ Tablice i wskaźniki 135 W przypadku tablicy jednowymiarowej, jak na przykład: KPVC=? odwołanie do C jest typu „wskaźnik do typu KPV”, a C — „wskaźnik do tablicy 10 elementów typu KPV”. W przypadku tablic dwuwymiarowych: KPVCTTC[=04195?=0 1.7/05? odwołanie do CTTC[ jest typu „wskaźnik do tablicy 0 1.7/05 elementów typu KPV”, na- tomiast CTTC[ — „wskaźnik do tablicy 04195 tablic o 0 1.7/05 elementów typu KPV”. 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ć wskaźnik do tablicy? Odpowiedź: Zastanów się, czy rzeczywiście go potrzebujesz. Kiedy ktoś mówi o wskaź- niku do tablicy, ma zazwyczaj na myśli wskaźnik do jej pierwszego elementu. Zamiast wskaźnika do tablicy czasem lepiej użyć wskaźnika do jednego z elementów tablicy. Tablice elementów typu 6 stają się w wyrażeniach wskaźnikami do typu 6 (zobacz pytanie 6.3), co jest bardzo wygodne. Indeksowanie albo zwiększanie po- wstałego tak wskaźnika pozwala na dostęp do elementów tablicy. Rzeczywiste wskaź- niki do tablic, kiedy są indeksowane lub zwiększane, „przechodzą” przez całe tablice i są przydatne tylko, gdy operujemy na tablicach tablic6 (zobacz pytanie 6.18). Jeżeli naprawdę potrzebujesz wskaźnika do całej tablicy, zadeklaruj go na przykład tak: KPV CR =0?, gdzie 0 to rozmiar tablicy (zobacz też pytanie 1.21). Jeżeli rozmiar tablicy jest nieznany, 0 można teoretycznie pominąć, ale zadeklarowany w ten sposób „wskaźnik do tablicy nieznanego rozmiaru” jest bezużyteczny. Poniższe przykłady pokazują różnice między zwykłymi wskaźnikami a wskaźnikami do tablic. Przy założeniu, że obowiązują deklaracje: KPVC=?]_ KPVC=?=?]]_]__ KPV KR YUMCļPKMFQV[RWKPV  KPV CR =? YUMCļPKMFQVCDNKE[GNGOGPVÎYVG[RWKPV  możemy użyć wskaźnika do typu KPV, KR, aby operować na jednowymiarowej tabli- cy C: k 6 Rozumowanie to dotyczy oczywiście również tablic trój- i więcejwymiarowych. 136 Programowanie w języku C. FAQ KRC RTKPVH F KR  KR  RTKPVH F P KR  Ten fragment kodu wydrukuje:  Jednak próba użycia wskaźnika do tablicy, CR, na C: CRC RTKPVH F CR  CR  Ļ.   RTKPVH F P CR  CEJQYCPKGPKGFGHKPKQYCPG G spowodowałaby wypisanie 0 i zachowanie niezdefiniowane (od wypisania przypad- kowej wartości do błędu w czasie wykonania) w momencie drugiego wywołania funk- cji RTKPVH. Wskaźnik do tablicy może się przydać, kiedy operujemy na tablicy tablic, na przykład C: CRC RTKPVH FF P CR =? CR =?  CR  RTGEJQFKO[FQPCUVúRPGL RQF GVCDNKE[  RTKPVH FF P CR =? CR =?  Ten fragment kodu drukuje:   Zobacz też pytanie 6.12. Referencje: ANSI §3.2.2.1 ISO §6.2.2.1 Dynamiczne tworzenie tablic Bliski związek tablic i wskaźników ułatwia symulowanie tablic o rozmiarze określo- nym w czasie działania programu za pomocą wskaźników do dynamicznie przydzie- lonych obszarów pamięci. 6.14 Pytanie: Jak określić rozmiar tablicy w czasie działania programu? Jak uniknąć tablic o z góry ustalonym rozmiarze? Odpowiedź: Odpowiedniość tablic i wskaźników (zobacz pytanie 6.3) pozwala „sy- mulować” tablice dynamiczne za pomocą wskaźnika do obszaru pamięci, dostarczo- nego przez funkcję OCNNQE. Po wykonaniu: Rozdział 6. ♦ Tablice i wskaźniki 137 KPENWFGUVFNKDJ KPV F[PCTTC[ KPV OCNNQE  UKGQH KPV  (i jeżeli wywołanie funkcji OCNNQE się powiedzie) możesz odwoływać się do F[PCT TC[=K? (dla K od 0 do 9) tak, jakby F[PCTTC[ była zwykłą, statycznie utworzoną tablicą (KPVC=?). Zobacz również pytania 6.16, 7.28 i 7.29. 6.15 Pytanie: Jak zadeklarować lokalną tablicę o rozmiarze równym tablicy przeka- zanej jako parametr? Odpowiedź: W języku C nie można tego zrobić. Rozmiary tablic muszą być znane w czasie kompilacji (Kompilator GNU C dopuszcza możliwość deklarowania tablic o zmiennym rozmiarze jako rozszerzenie; znalazło się ono również w standardzie C99). Możesz użyć funkcji OCNNQE, aby stworzyć „tablicę dynamiczną”, ale pamię- taj o zwolnieniu jej funkcją HTGG. Zobacz też pytania 6.14, 6.16, 6.19, 7.22 i może również 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 większości przypadków najlepiej stworzyć tablicę7 wskaźników do wskaźników, a następnie każdemu ze wskaźników przypisać adres dynamicznie przy- dzielonego „wiersza”. Oto przykład dla tablicy dwuwymiarowej: KPENWFGUVFNKDJ KPV CTTC[ KPV OCNNQE PTQYU UKGQH KPV  HQT KKPTQYUK CTTC[=K? KPV OCNNQE PEQNWOPU UKGQH KPV  W rzeczywistym kodzie należałoby oczywiście sprawdzić wszystkie wartości zwró- cone przez funkcję OCNNQE. Jeżeli nie zamierzasz zmieniać długości wierszy, a za to chciałbyś, aby przydzielony tablicy obszar pamięci był ciągły, wystarczy odrobina arytmetyki na wskaźnikach: KPV CTTC[ KPV OCNNQE PTQYU UKGQH KPV  CTTC[=? KPV OCNNQE PTQYU PEQNWOPU UKGQH KPV G HQT KKPTQYUK CTTC[=K?CTTC[=? K PEQNWOPU k 7 Mówiąc ściśle, nie są to tablice, ale raczej obiekty używane jak tablice, zobacz pytanie 6.14. 138 Programowanie w języku C. FAQ W obu przypadkach (to znaczy tablic CTTC[ i CTTC[) tablice dynamiczne można in- deksować za pomocą normalnych operatorów: CTTC[Z=K?=L? (dla ŭK04195 i ŭ L0 1.7/05). Poniższy rysunek przedstawia schematycznie „układ” wierszy w tabli- cach CTTC[ i CTTC[. Jeżeli dwa odwołania do pamięci w tym schemacie są z jakichś powodów nie do przy- jęcia8, możesz zasymulować tablicę dwuwymiarową dynamicznie stworzoną tablicą jednowymiarową: KPV CTTC[ KPV OCNNQE PTQYU PEQNWOPU UKGQH KPV G  Jednak w takim przypadku obliczanie indeksów musisz wykonywać własnoręcznie. Aby odwołać się do elementu o współrzędnych K,L, należałoby użyć wyrażenia CT TC[=K PEQNWOPU L?9. Takiej tablicy nie można jednak przekazać do funkcji, któ- ra akceptuje tablicę wielowymiarową. Zobacz też pytanie 6.19. Możesz też użyć wskaźników do tablic: KPV CTTC[ =0 1.7/05?  KPV =0 1.7/05? OCNNQE PTQYU UKGQH CTTC[  k 8 9 Zauważ jednak, że dwukrotne odwołanie do tablicy nie musi być wcale mniej efektywne niż jawne mnożenie indeksów. Jawne obliczanie indeksu można ukryć w makrodefinicji, na przykład: FGHKPG#TTC[CEEGU CKL C = K  PEQNWOPU  L ? . Jednak wywołanie takiej makrodefinicji, z nawiasami i przecinkami, nie kojarzyłoby się z normalną składnią dostępu do tablic. Makrodefinicja musiałaby mieć również dostęp do jednego z wymiarów tablicy. Rozdział 6. ♦ Tablice i wskaźniki 139 albo nawet: KPV CTTC[ =04195?=0 1.7/05?   KPV =04195?=0 1.7/05? OCNNQE UKGQH CTTC[  Jednak składnia odwołania do elementów wskazywanych tablic robi się coraz bar- dziej skomplikowana (w przypadku CTTC[ trzeba pisać CTTC[ =K?=L?). Najwyżej jeden wymiar tablicy można określić w czasie działania programu. Używając tych technik, nie można oczywiście zapomnieć o zwolnieniu przydzielonej pamięci, kiedy nie jest już potrzebna. W przypadku tablic CTTC[ i CTTC[ wymaga to kilku kroków (zobacz też pytanie 7.23): HQT KKPTQYUK HTGG XQKF CTTC[=K?  HTGG XQKF CTTC[  HTGG XQKF CTTC[=?  HTGG XQKF CTTC[  Nie możesz też mieszać tablic przydzielonych dynamicznie ze zwykłymi, utworzo- nymi statycznie (zobacz pytanie 6.20, a także 6.18). Powyższe techniki można oczywiście rozszerzyć na trzy i więcej wymiarów. Oto „trój- wymiarowa” wersja pierwszego sposobu: KPV CF KPV OCNNQE ZFKO UKGQH KPV  HQT KKZFKOK ] CF=K? KPV OCNNQE [FKO UKGQH KPV  HQT LL[FKOL CF=K?=L? KPV OCNNQE FKO UKGQH KPV  _ Zobacz też pytanie 20.2. 6.17 Pytanie: Wpadłem na fajny pomysł — jeżeli napiszę: KPVTGCNCTTC[=? KPV CTTC[TGCNCTTC[=Ō? mogę traktować tablicę CTTC[ tak, jakby jej indeksy zaczynały się od 1. Czy to poprawne? Odpowiedź: Chociaż taka technika może wydawać się atrakcyjna (była nawet używa- na w starszych wydaniach książki Numerical Recipes in C), nie jest zgodna ze Stan- dardem języka C. Arytmetyka wskaźników zdefiniowana jest tylko, jeżeli wartość wskaźnika pozostaje w obrębie tego samego przydzielonego bloku pamięci albo umownego „końcowego” elementu tuż za nim. W przeciwnym wypadku zachowanie programu jest niezdefiniowane, nawet jeżeli nie następuje dereferencja wskaźnika. Kod w pytaniu oblicza wskaźnik do obszaru przed początkiem tablicy TGCNCTTC[. 140 Programowanie w języku C. FAQ W momencie odejmowania offsetu może wystąpić błąd wygenerowania nieprawidło- wego adresu (na przykład gdyby obliczenie adresu spowodowało „zawinięcie” wokół początku segmentu pamięci). Referencje: K R2 §5.3, §5.4, §A7.7 ANSI §3.3.6 ISO §6.3.6 Rationale §3.2.2.3 Funkcje a tablice wielowymiarowe Trudno jest przekazywać tablice wielowymiarowe do funkcji z zachowaniem pełnej ogólności. Podmiana parametrów tablicowych na wskaźniki (zobacz pytanie 6.4) oznacza, że funkcja, która akceptuje zwykłe tablice, może również przyjmować tabli- ce o dowolnej długości, co jest wygodne. Jednak podmiana dotyczy tylko najbardziej „zewnętrznej” tablicy, pozostałe wymiary nie mogą być zmienne. Problem ten wyni- ka z faktu, że w języku C wymiary tablic muszą być zawsze znane w czasie kompila- cji. Nie można ich określić, przekazując na przykład dodatkowy parametr. 6.18 Pytanie: Mój kompilator zgłasza błędy, kiedy przekazuję tablicę dwuwymiarową do funkcji przyjmującej wskaźnik do wskaźnika. Dlaczego? Odpowiedź: Zasada (zobacz pytanie 6.3), na mocy której tablice „degenerują” się do wskaźników, nie działa rekurencyjnie. Tablica dwuwymiarowa (czyli w języku C ta- blica tablic) staje się wskaźnikiem do tablicy, nie wskaźnikiem do wskaźnika. Wskaź- niki do tablic powodują dużo nieporozumień, dlatego należy ich używać ostrożnie. Zobacz pytanie 6.13 (nieporozumienia wzmaga fakt, że istnieją kompilatory, w tym stare wersje REE i oparte na nich wersje programu NKPV, które niepoprawnie pozwalają przypisywać wielowymiarowe tablice do wskaźników na wskaźniki). Jeżeli przekazujesz dwuwymiarową tablicę do funkcji: KPVCTTC[=04195?=0 1.7/05? H CTTC[  jej deklaracja musi mieć postać: H KPVC=?=0 1.7/05? ]ŗ_ albo: H KPV CR =0 1.7/05?  CRVQYUMCļPKMPCVCDNKEú  ]ŗ_ Rozdział 6. ♦ Tablice i wskaźniki 141 W przypadku pierwszej deklaracji kompilator wykonuje podmianę typu parametru z „tablicy tablic” na „wskaźnik do tablicy” (zobacz pytania 6.3 i 6.4). W drugiej de- klaracji jawnie określamy typ jako wskaźnik do tablicy. Ponieważ wywoływana funk- cja nie przydziela pamięci dla tablicy, nie musi znać jej obu wymiarów — liczba wierszy, 04195, może zostać pominięta w deklaracji. „Kształt” tablicy jest jednak wciąż ważny, więc wymiar 0 1.7/05 (i wszystkie kolejne w przypadku tablic wielowymia- rowych) musi zostać wyspecyfikowany. Jeżeli deklaracja funkcji wskazuje, że oczekuje ona wskaźnika do wskaźnika, naj- prawdopodobniej nie można przekazać jej tablicy dwuwymiarowej bezpośrednio. Mo- że być wtedy potrzebny pomocniczy wskaźnik: GZVGTPI KPV KRR  KPV KRCTTC[=?=? I KR  $;ç/1Ľ Ļ.   Taki sposób wywołania jest jednak mylący i prawie na pewno nieprawidłowy. Tabli- ca została „spłaszczona” — straciliśmy informację o jej szerokości. 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, które przyjmują tablice dwuwymiarowe, jeżeli nie znam ich „szerokości” w czasie kompilacji? Odpowiedź: To nie jest łatwe. Jednym ze sposobów jest przekazanie wskaźnika do elementu o indeksach =?=? wraz z obydwoma wymiarami i „ręczne” obliczanie in- deksów: H KPV CT[RKPVPTQYUKPVPEQNWOPU ]ŗCT[R=K PEQNWOPU L?ŗ QFYQđCPKGFQGNGOGPVWCTTCG[=K?=L? _ Aby jawnie obliczyć indeks elementu, potrzebujemy wartości PEQNWOPU („szerokości” każdego wiersza), nie PTQYU (liczby wierszy). Łatwo się tu pomylić. Funkcji tej można przekazać tablicę CTTC[ z pytania 6.18 w następujący sposób: H CTTC[=?=?041950 1.7/05  Trzeba jednak zauważyć, że program, w którym indeksy w tablicy wielowymiarowej obliczane są „ręcznie”, nie jest ściśle zgodny ze Standardem ANSI języka C. Zgodnie z oficjalną interpretacją, dostęp do elementu CTTC[=?=? =Z? jest niezdefiniowany, jeżeli Z 0 1.7/05. 142 Programowanie w języku C. FAQ Kompilator GNU C pozwala definiować lokalne tablice o rozmiarach ustalonych przez argumenty funkcji, możliwość ta pojawiła się też w Standardzie C99. Jeżeli chcesz stworzyć funkcję, która przyjmować będzie tablice wielowymiarowe o różnych rozmiarach, jednym z rozwiązań jest dynamiczne symulowanie takich ta- blic, jak w pytaniu 6.16. Zobacz też pytania 6.15, 6.18 i 6.20. Referencje: ANSI §3.3.6 ISO §6.3.6 6.20 Pytanie: Jak korzystać jednocześnie z wielowymiarowych tablic przydzielanych statycznie i dynamicznie przy przekazywaniu ich do funkcji? Odpowiedź: Nie ma jednej, uniwersalnej metody. Mając deklaracje: KPVCTTC[=04195?=0 1.7/05? KPV CTTC[ MCľF[YKGTUQUQDPQ  KPV CTTC[ EKæIđ[QDUCTRCOKúEK  KPV CTTC[ VCDNKECURđCUEQPC  KPV CTTC[ =0 1.7/05? KPV CTTC[ =04195?=0 1.7/05? gdzie wskaźniki są zainicjalizowane tak, jak w pytaniu 6.16, i funkcje, zadeklarowane jako: H KPVC=?=0 1.7/05?KPVPTQYUKPVPEQNWOPU  H KPV CT[RKPVPTQYUKPVPEQNWOPU  H KPV RRKPVPTQYUKPVPEQNWOPU  gdzie funkcja H akceptuje „zwykłą” tablicę dwuwymiarową, funkcja H — „spłasz- czoną” tablicę dwuwymiarową, a funkcja H — tablicę symulowaną przez wskaźnik do wskaźnika (zobacz pytania 6.18 i 6.19), poniższe wywołania funkcji działają zgodnie z oczekiwaniami: H CTTC[041950 1.7/05  H CTTC[PTQYU0 1.7/05  H CTTC[041950 1.7/05  H CTTC[=?=?041950 1.7/05  H CTTC[041950 1.7/05  H CTTC[PTQYUPEQNWOPU  H CTTC[PTQYUPEQNWOPU  H CTTC[PTQYU0 1.7/05  H CTTC[041950 1.7/05  H CTTC[PTQYUPEQNWOPU  H CTTC[PTQYUPEQNWOPU  Rozdział 6. ♦ Tablice i wskaźniki 143 Poniższe dwa wywołania powinny działać prawidłowo na większości systemów, ale wymagają „podejrzanych” rzutowań i działają tylko, jeżeli dynamiczna wartość PEQ NWOPU równa jest statycznej 0 1.7/05: H KPV =0 1.7/05? CTTC[ PTQYUPEQNWOPU  H KPV =0 1.7/05? CTTC[PTQYUPEQNWOPU  Z wyżej wymienionych tylko funkcja H może przyjmować tablice statyczne i przy- dzielone dynamicznie, chociaż nie będzie działać dla tradycyjnej implementacji CTTC[, czyli „każdy wiersz osobno”. Pamiętaj jednak, że przekazywanie CTTC[=?=? (albo CTTC[) do funkcji H nie jest ściśle zgodne ze Standardem — zobacz pytanie 6.19. Jeżeli rozumiesz, dlaczego wszystkie wyżej wymienione sposoby przekazywania tablic wielowymiarowych do funkcji działają oraz dlaczego kombinacje, których tu nie przed- stawiono, nie działają, możesz uznać, że bardzo dobrze rozumiesz tablice i wskaźniki w języku C. Zamiast jednak zaprzątać sobie głowę tymi wszystkimi trudnymi regułami, możesz zastosować dużo prostsze rozwiązanie: wszystkie tablice wielowymiarowe twórz dy- namicznie, jak w pytaniu 6.16. Jeżeli nie będzie statycznych tablic wielowymiaro- wych — wszystkie będą przydzielane jak CTTC[ lub CTTC[ w pytaniu 6.16 — wtedy wszystkie funkcje mogą mieć deklaracje podobne do H. Rozmiary tablic Operator UKGQH zwraca rozmiar tablicy, ale tylko wtedy, gdy jest on znany, a odnie- sienie do tablicy nie zredukowało się do wskaźnika. 6.21 Pytanie: Dlaczego operator UKGQH nie zwraca poprawnego rozmiaru tablicy, która jest parametrem funkcji? Moja testowa funkcja wypisuje 4, zamiast 10: H EJCTC=? ] KPVKUKGQH C  RTKPVH F PK  _ Odpowiedź: Kompilator podmienia typ parametru z tablicy na wskaźnik (w tym przy- padku EJCT , zobacz pytanie 6.4). Operator UKGQH zwraca w tym wypadku rozmiar wskaźnika. Zobacz też pytania 1.24 i 7.28. Referencje: H S §7.5.2 144 6.22 Programowanie w języku C. FAQ Pytanie: Jak kod w pliku, w którym tablica zadeklarowana jest jako GZVGTP (jest zdefiniowana i jej rozmiar jest określony w innym pliku), może określić jej wiel- kość? Operator UKGQH nie działa na niej. Odpowiedź: Zobacz pytanie 1.24. 6.23 Pytanie: Jak mogę określić liczbę elementów tablicy, jeżeli operator UKGQH zwraca rozmiar w bajtach? Odpowiedź: Po prostu podziel rozmiar całej tablicy przez rozmiar jednego elementu: KPVCTTC[=?]_ KPVPCTTC[UKGQH CTTC[ UKGQH CTTC[=?  Referencje: ANSI §3.3.3.4 ISO §6.3.3.4
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Programowanie w języku C. FAQ
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: