Podręcznik
Wersja podręcznika: 1.0
Data publikacji: 01.01.2022 r.
2. Typy danych
2.1. Wprowadzenie
Zanim przejdziemy do dokładnego opisywania typów pora na jeszcze jedną uwagę, która& nie jest oczywista na pierwszy rzut oka, oraz jest cechą charakterystyczną C / C++, lecz już niekoniecznie w przypadku innych języków programowania.
- zwracana wartość może być tzw. wartością która oznacza brak wartości ( void),
- zwracaną wartość można pominąć (nie „przechwycić” jej) – co jest niemożliwe w wielu innych językach. Dlatego poprawne jest napisanie po prostu instrukcji 2+2; (pomijając kompletny brak jej sensu).
Zmienne, stałe i L-wartości
To, co jest charakterystyczne zarówno dla zmiennych, jak i stałych występujących w C++, to wspomniana na początku silna kontrola typów. W praktyce oznacza to, że zmienna czy stała musi mieć raz przypisany w momencie definicji, i potem do końca jej czasu życia niezmienny – typ danych które może przechowywać. Typ jest niezmienny – lecz od tego czy może się zmieniać wartość, czy nie – zależy czy mamy do czynienia ze zmienną czy ze stałą. W składni C++ to rozróżnienie jest zaznaczone, lecz często nie do końca poważnie brane przez kompilator.
Ogólnie stałe definiuje się i deklaruje tak jak zmienne – jedyną różnicą jest dodanie przedrostka const przed wyspecyfikowaniem typu. Podanie const w założeniu uniemożliwia zmianę wartości tak oznaczonej zmiennej w zasięgu jej widoczności bez jawnego rzutowania const cast. No właśnie . . . bez jawnego rzutowana . . . to co to za stała którą można zmienić w zmienną? Dlatego wspomniałem, że const nie jest brany poważnie przez kompilator. Jeśli włączona jest optymalizacja, kompilator sprawdza, czy istnieje w programie choćby teoretyczna możliwość zmiany wartości oznaczonej jako stała – i jeśli tak, to ignoruje przyrostek const tworząc zamiast tego zmienną, której wartości nie można prosto zmienić. W przeciwnym wypadku często wartości stałych są bezpośrednio rozwijane w kodzie programu, i nie jest im w ogóle przydzielana pamięć z obszaru pamięci danych.
Z pojęciami zmiennej i stałej ściśle związane jest pojęcie L-wartości. Ogólnie można przyjąć, że:
W praktyce L-wartościami najczęściej są zmienne bez modyfikatora const, ale także – np. parametry funkcji z tym modyfikatorem. Od powyższej definicji jest wyjątek – w przypadku definiowania stałej połączonego z jej inicjacją, stała stoi po lewej stronie równania – lecz nie jest ona L-wartością . . . wartość jest wyliczana na etapie kompilacji, a operator przypisania jest wtedy traktowany jako operator inicjacji. Dlatego też w nowych wersjach standardu języka raczej nastawiamy się na inicjację przy stosowaniu nawiasów klamrowych - a nie przy wykorzystaniu składni ze znakiem przypisania.
Na razie parametrami funkcji i innymi skomplikowanymi zagadnieniami nie zajmujmy się, natomiast sama definicja L-wartości mówi nam, dlaczego poprawny jest poniższy kod:
double r = 12.3;
double x;
x = 2.0*M_PI*r;
x jest zmienną – więc jest L-wartością, natomiast niepoprawny jest ten kod:
double x;
2.0*M_PI*r = x;
Wartość wyrażenia 2*M PI*r nie jest L-wartością.
Ogólny podział typów danych
W pierwszym przybliżeniu wszelkie dostępne typy danych w języku C++ można podzielić na następujące grupy:
- Typy podstawowe. Wśród nich wyróżniamy typy ściśle powiązane z architekturą sprzętową komputera (logiczne, znakowe, całkowite, zmiennoprzecinkowe), typ wyliczeniowy i typ oznaczający brak wartości
- Typy pochodne dla typów podstawowych, czyli funkcje, wskaźniki i referencje
- Typy złożone, czyli tablice, struktury i klasy.
Wspomniany podział nie jest jedynym możliwym, wśród wspomnianych typów można na przykład wydzielić typy przeliczalne:
Do typów przeliczalnych zaliczamy typ logiczny, znakowy, całkowitoliczbowy i wyliczeniowy. Wyróżnienie typów przeliczalnych jest istotne z tego względu, że w niektórych instrukcjach (np. switch) zmienna sterująca musi być przeliczalna. Istnieje także wydzielona grupa typów arytmetycznych: