5 WSKAŹNIKI I TABLICE o specjalną wartość wskaźnikową. Stała NULL jest zdefiniowana w nagłów); <Stdio.h>. Odtąd będziemy się nią posługiwać.
Testy w rodzaju:
if (allocbuf + ALLOCSIZE - allocp >= n) { /* wystarczy miejsca */
lub
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
ilustrują kilka ważnych cech arytmetyki na wskaźnikach. Po pierwsze, przy pewnyc l ograniczeniach wskaźniki można ze sobą porównywać. Jeżeli p i q wskazują na elementy tej samej tablicy, to relacje ==, !=, <, >= itp. działają poprawnie. Na przykła:|
jest prawdą, jeśli p wskazuje na wcześniejszy element tablicy niż q. Dowolny wskaż nik zawsze można przyrównać do zera. Natomiast skutek operacji arytmetycznych luj porównań dla wskaźników odwołujących się do elementów z różnych tablic jest nfc określony. (Z jednym wyjątkiem: w arytmetyce na wskaźnikach można posłużyć s.j adresem pierwszego miejsca po ostatnim elemencie tablicy.)
Po drugie, obserwowaliśmy już, że wskaźnik i wartość całkowita mogą być dodawać;I i odejmowane. Konstrukcja
p + n
oznacza adres n-tego elementu od miejsca, na które wskazuje p. Jest to prawdziw; niezależnie od tego, jakiego rodzaju obiekty wskazuje p: wartość n jest skalowar odpowiednio do rozmiaru obiektów wskazywanych przez p, wynikającego z deklar: cji p. Jeśli typ int zajmuje np. cztery bajty, to dla wskaźnika do obiektów typu ir| czynnikiem skalującym wartość n jest cztery. L
Odejmowanie wskaźników jest także poprawne: jeżeli p i q wskazują na elementy^ samej talicy i p<q, to q-p+1 jest liczbą elementów między p i q (razem z q). Z fak tego można skorzystać w jeszcze jednej wersji funkcji strlen:
I* strlen: podaj długość tekstu s */ int strlen(char *s)
char *p = s; 3
while (*p != ’\0’)
P++;
return p - s;
5.5 WSKAŹNIKI ZNAKOWE I FUNKCJE ____I Powered by I
Wskaźnik p jest w deklaracji zainicjowany wartością s po to, by wska^*v^se^rósw ■ J szy znak tekstu. W pętli while bada się po kolei każdy znak do napotkania znaku ’\0’ kończącego tekst. Wskaźnik p odnosi się do znaków, zatem operacja p++ za każdym razem przesuwa p do następnego znaku, a p-s podaje liczbę znaków, o jaką go przesunięto, czyli długość tekstu. (Liczba znaków w tekście może być zbyt duża, aby mogła być przechowywana w zmiennej typu int. W nagłówku <stddef.h> zdefiniowano typ ptrdiff_i, który jest wystarczająco obszerny, aby pomieścić wartość (ze znakiem) różnicy dwóch wskaźników. Gdybyśmy jednak byli bardzo ostrożni, wówczas dla zwracanej przez strlen wartości powinniśmy użyć typu size_t, aby dopasować ją do wersji z biblioteki standardowej: size_l jest typem wartości całkowitej bez znaku, otrzymywanej za pomocą operatora sizeof.)
Zasady arytmetyki na wskaźnikach są konsekwentne: gdybyśmy mieli do czynienia z obiektami typu float, które zajmują więcej pamięci niż znaki, i gdyby p był wskaź-nikem do obiektów typu float, wówczas operacja p++ spowodowałaby przesunięcie p do następnego obiektu typu float. Zatem moglibyśmy napisać inną wersję dystrybutora pamięci przydzielającego pamięć dla obiektów zmiennopozycyjnych (zamiast znaków), zamieniając jedynie słowa char na float w funkcjach alloc i afree. Wszystkie operacje na wskaźnikach są automatycznie dostosowywane do rozmiaru wskazywanych obiektów.
Do poprawnych operacji wskaźnikowych należą: przypisanie wskaźników do obiektów tego samego typu, dodawanie lub odejmowanie wskaźnika i liczby całkowitej, odejmowanie bądź porównywanie dwóch wskaźników do elementów tej samej tablicy oraz przypisanie wskaźnikowi wartości zero lub przyrównanie wskaźnika do zera. Wszystkie inne operacje na wskaźnikach są nielegalne. Nie wolno dodawać do siebie dwóch wskaźników ani ich mnożyć, dzielić, przesuwać albo składać z maskami, ani też dodawać do nich liczb typu float lub double. Nie wolno nawet - z wyjątkiem typu void * - wskaźnikowi do obiektów jednego typu przypisać bez rzutowania wskaźnika do obiektów innego typu.
Stała napisowa, na przykład taka:
"Jestem napisem”
jest tablicą znaków. W wewnętrznej reprezentacji taka tablica jest zakończona znakiem '\0\ więc programy mogą znaleźć jej koniec. Długość tekstu w pamięci jest zatem o jeden większa od liczby znaków zawartych między dwoma znakami cudzysłowu.
143