Stałe czyli jak zapisywać dane.

Stała jest to zapis posiadający stałą wartość, nie znieniającą się w trakcie działania programu. Na przykład zapis 67, to stała mająca wartość liczby 67. To tylko jeden ze sposobów zapisania tej samej wartości. Można ją też zapisać jako 0x43 lub 'C'. Po co taka różnorodność?

Niektóre obliczenia wymagają znajomości systemów liczbowych innych niż powszechnie używany system dziesiętny. W komputerach zwykło się od dawna używać systemów: ósemkowego i szesnastkowego. Dla powyższego przykładu: w matematyce liczbę 67 w systemie szesnastkowym zapisuje się 4316, ale jak to zrobić na klawiaturze komputera nie mającego standardowo możliwości zapisania takiej "obniżonej" szesnastki? W językach C/C++ wprowadzono więc umowę, według której zapisuje się stałe.


Wymienione tu zostały stałe całkowite (ang. integer). Oprócz tego często w programach wykonuje się obliczenia związane z tekstem, a konkretnie znakami wchodzącymi w jego skład. Równie dawno jak system ósemkowy, wymyślony został standard kodowania podstawowych znaków używanych w napisach. Mowa tu o kodach ASCII. Można w ten sposób wyrazić liczby będące kodami widocznych (tzw. drukowalnych) znaków. A co ze znakami niewidocznymi (niedrukowalnymi, tzw. białymi), jak tabulacja, przejście do nowej linii i inne? I wreszcie: co z apostrofem i backslash'em? We wspomnianych apostrofach pisze się najpierw \ (backslash), a po nim jednym ze sposobów można wyrazić dany znak. Oto możliwości stałych znakowych: Różne komputery różnie kodują znak(i) końca wiersza. W niektórych systemach wystarczy wysłanie samego znaku CR, w innych samego LF, a w jeszcze innych trzeba wysłać po kolei parę CR i LF. Języki C/C++ uwalniają programistę od tego zamieszania. Końcem wiersza jest tam zawsze '\n', choćby nawet miał on kod różny od wymienionych (np. w Atari ma on kod 155). Wysłanie tego znaku na ekran powoduje przejście kursora do pierwszego znaku w nowej linii, na drukarkę - przejście głowicy o jeden wiersz niżej i tam dalsze drukowanie od początku wiersza itd.

Stałych znakowych można uzywać na równych prawach z pozostałymi stałymi całkowitymi, tzn. tam gdzie należałoby użyć zapisu np. liczby dziesiętnej lub ósemkowej, można użyć stałej znakowej i odwrotnie, zamiast stałej znakowej można użyć liczby, która będzie reprezentowała kod ASCII tego znaku. Na przykład:
znak='A';
znak='\x41';
znak=65;
znak=0101;

Powyższe zapisy są sobie całkowicie równoważne.

Jeśli chodzi o stałe całkowite (z wyjątkiem znakowych), zapis ich można zakończyć tzw. przyrostkiem określającym typ takiej stałej. Znak l lub L (litera el) oznacza, że stała jest tzw. długa (ang. long). Znak u lub U (litera u) oznacza, że stała reprezentuje tzw. liczbę bez znaku (ang. unsigned). Przyrostki można ze sobą łączyć.
Przykłady:
10 - stała całkowita dziesiętna;
10L - stała całkowita długa dziesiętna;
10U - stała całkowita bez znaku dziesiętna;
10LU lub 10UL - stała całkowita długa bez znaku dziesiętna;
0xFUL - stała całkowita długa bez znaku szesnastkowa (o wartości 15).
Na następnej podstronie przeczytasz o typach danych, wtedy z pewnością zrozumiesz zastosowanie tych przyrostków.


Oprócz powyższych stałych, do obliczeń prowadzonych w pewnym stopniu dokładności używa się stałych rzeczywistych (ang. real lub float). Należy tu pamiętać, że do oddzielania części całkowitej od ułamkowej używa się znaku kropki (a nie przecinka, jak w Polsce). Oprócz przedstawienia w takiej liczbie części całkowitej i ułamkowej, dodatkowo przedstawia się w niej tzw. eksponent. Jest to potęga, do jakiej należałoby podnieść liczbę 10, aby uzyskać rząd reprezentowanej liczby. Sposób w jaki zapisuje się taką liczbę często nazywa się zapisem naukowym lub notacją naukową. Wygląda to tak, że po liczbie rzeczywistej pisze się literę e lub E, a po niej liczbę stanowiącą eksponent.
Oto różne przykłady:
2000 - stała całkowita (to nie jest to samo co 2000.0);
2000.0 - stała rzeczywista w normalnym zapisie;
2e3 lub 2e+3 - stała rzeczywista w zapisie naukowym (o wartości 2000.0);
0.002 lub .002 - stała rzeczywista w normalnym zapisie (można opuścić zero);
2.0e-3 lub 2e-3 - stała rzeczywista w zapisie naukowym (o wartości 0.002).

Ogólnie mówiąc, przykładowy zapis 2.4e-3 reprezentuje wartość 2.4*10-3.

W stałych rzeczywistych można również używać przyrostków. Są one oczywiście inne i mają inne znaczenie niż w stałych całkowitych. Podobnie jednak jak tam, tutaj one też określają typ stałej. Znak f lub F (litera ef) oznacza, że stała jest typu float (typ rzeczywisty pojedynczej precyzji). Znak l lub L (litera el) oznacza, że stała jest typu long double (typ rzeczywisty podwójnej precyzji długi). Przyrostków nie można łączyć ze sobą. Brak przyrostka oznacza, że stała jest typu double (typ rzeczywisty podwójnej precyzji).


Tylko dwa rodzaje wyżej wymienionych stałych sprawiają, że przed programistą otwierają się ogromne możliwości. Brakuje tylko możliwości przedstawiania całych ciągów znakowych. W C/C++ istnieją stałe tekstowe będące takimi ciągami znaków. W innych językach programowania (jak np. BASIC lub Pascal) stałe tekstowe reprezentują ciąg kolejnych znaków, z których się składają, jako całość, tzn. wartością stałej tekstowej jest cały tekst. Tu jest trochę inaczej. Wystąpienie w programie stałej tekstowej powoduje, że kompilator rezerwuje sobie gdzieś w pamięci miejsce na kolejne znaki tej stałej, sama zaś stała reprezentuje adres w pamięci, pod którym znajduje się pierwszy znak, w kolejnych bajtach są kolejne znaki, za nimi zaś (jako sygnalizacja zakończenia tego "bloku" tekstowego), w następnym bajcie, jest umieszczony znak NULL o kodzie ASCII równym 0. Kiedy poznasz wskaźniki, dowiesz się, że wartością takiej stałej jest wskaźnik na znaki (const char * ).

Jak się zapisuje stałe tekstowe? Wymagany ciąg znaków otacza się znakami " (cudzysłów). Początkującemu programiście często myli się apostrof (dla stałych znakowych) z cudzysłowem (dla stałych tekstowych). Dla zapamiętania proponuję nazywać sobie te znaki trochę inaczej: ' (apostrof) - pojedynczy cudzysłów (dla pojedynczych znaków), " (cudzysłów) - podwójny cudzysłów (dla wielu znaków). Z pewnością szybko ta zasada "wejdzie w krew" i będziesz używać tych znaków prawidłowo.

Podobnie jak w przypadku stałych znakowych, w stałych tekstowych nie można bezpośrednio "napisać" niektórych znaków. Wówczas w miejscu takiego znaku specjalnego umieszcza się znak \ (backslash), a po nim określa się znak specjalny. Wygląda to podobnie (z pewnymi wyjątkami), jak przy stałych znakowych.

Zostało to już napisane: na końcu każdej stałej tekstowej kompilator w pamięci nań zarezerwowanej umieszcza znak '\0' (NULL) jako sygnalizację końca ciągu znaków (nie mylić znaku NULL ze stałą kompilatora NULL). Znaku NULL zatem w stałych tekstowych używaj z rozwagą, wtedy gdy "wiesz co robisz".
Popatrzmy na poniższe przykłady:

"tekst"
Powyższa stała tekstowa reprezentuje adres (wskaźnik) na sześć (tak, tak, to nie błąd - sześć, nie pięć) znaków umieszczonych w pamięci: 't', 'e', 'k', 's', 't', '\0'.

"Plik z \"muzyczką\" znajduje się w katalogu:\nC:\\DANE\\MUZYKA"
Wartością tej stałej z kolei jest wskaźnik na obszar pamięci z innym ciągiem znaków. Gdyby znaki te wysłać na ekran lub drukarkę wyglądałoby to tak:
Plik z "muzyczką" znajduje się katalogu:
C:\DANE\MUZYKA

Oczywiście i po tych znakach w pamięci umieszczony jest znak NULL.

"raz\0dwa"
Stała ta użyta w niewłaściwy sposób może przyczynić się do kłopotów z zarządzaniem pamięcią przez kompilator. Może on bowiem "pomyśleć", że ciąg znaków kończy się już po słowie raz a nie dwa, jak być powinno. Wtedy zwalniając pamięć, bezpowrotnie stracimy cztery bajty zajmowane przez znaki: 'd', 'w', 'a', '\0'.


Na koniec warto wspomnieć jeszcze o dwóch rzeczach. Pierwszą z nich jest możliwość samodzielnego definiowania tzw. stałych wyliczanych (ang. enumeration). Związane jest to z definiowaniem typów wyliczeniowych. Druga rzecz, to deklaracje (definicje) tzw. stałych (ang. constant) obiektów. Sprawy te zostaną omówione w dalszych częściach tego opisu.

Powrót na początek