Wstęp

Najprościej opisać typy złożone jako typy budowane na bazie typów podstawowych. To w jaki sposób będą one przechowywane, jak będziemy się do nich odnosić, gdzie fizycznie będą przechowywane zależeć już będzie od specyfikacji konkretnego typu złożonego.  W dzisiejszym wpisie omówię pierwszy z serii typ złożony – tablice.

Tablica jest strukturą danych umożliwiającą przechowywanie wielu wartości konkretnego typu. Aby zadeklarować poprawnie tablicę należy:

  • przedstawić typ jej elementów
  • podać jej nazwę
  • sprecyzować jej pojemność.

Posłużę się przykładem aby przybliżyć ten opis.

int numbers[50];

Powyższa deklaracja utworzyła tablicę 50 elementów, do których możemy odwoływać się poprzez indeksy tablicy. Tablica n elementowa ma indeksy od 0 (pierwszy element) do n-1 (ostatni element tablicy).

Inicjalizacja

W c++ tablicę można zainicjalizować w następujący sposób:

// Inicjalizacja tablicy wartościami przypadkowymi, które znajdowały się w pamięci pod adresem utworzonej tablicy
int numbers1[2];

// inicjalizacja tablicy wartościami 100 oraz 200
int numbers2[2] = { 100,200 }; 

// inicjalizacja pierwszego elementu tablicy wartością 100, pozostałe wartości inicjalizowane są automatycznie wartościami 0
int numbers3[2] = { 100 }; 

// wszystkim elementom tablicy przypisywana jest wartość 0
int numbers4[2] = {}; 

// wszystkim elementom tablicy przypisywana jest wartość 0
int numbers5[2]{};

// w tym przypadku mimo braku sprecyzowania liczby elementów w nawiasach, kompilator policzy liczbę elementów inicjalizujących tablicę I stworzy tablicę o takim właśnie rozmiarze
int numbers5[] = {100,200,300}; 

Aby bardziej przybliżyć powyższe formułki, zaprezentuję prosty przykład, w którym zapiszemy 5 liczb całkowitych podanych przez użytkownika do tabeli obliczając jednocześnie ich sumę.

#include "stdafx.h"
#include <iostream>;
using namespace std;

int main()
{

const int count = 5;
int numbers[count];
int sum = 0;
for (int i = 0; i &lt; count; i++)
{
  cout << "numbers[" << i << "] = ";
  cin >> numbers[i];
  sum += numbers[i];
}

cout << endl << "Suma wszystkich podanych liczb wynosi " << sum << endl;
cout << "Rozmiar tablicy w bajtach sizeof(numbers) = " << sizeof(numbers) << endl; // 5 * sizeof(int)

cin.get();
cin.get();
return 0;
}

Podsumowanie

Tablice to struktura danych, która umożliwa nam na przechowywanie wielu wartości tego samego typu w jednym obiekcie. Do jej wartości odwołujemy się poprzez indeksy, gdzie indeks pierwszego elementu to 0, a ostatniego to n-1; gdzie n to liczba elementów. Używając operatora sizeof(nazwa_tablicy) otrzymamy liczbę bajtów jaką zajmuje nasza tablica.

Wstęp

Typy danych w języku C++ dzielą się na dwie kategorie: typy podstawowe oraz typy złożone.
W niniejszym poście pokrótce postaram się przedstawić typy podstawowe.
Typy podstawowe również mają swój podział.  Dzielą się na całkowitoliczbowe (do których nalezą również typy znakowe), zmiennoprzecinkowe oraz typ bool.

 

Liczby całkowite

Liczby całkowite to typy które pozbawione są części ułamkowej np. -123, 0 czy 54321.
Rozróżniamy kilka typów całkowitoliczbowych o różnej wielkości (ilości bajtów), przez co zmienne tych typów mogą przechowywać różne zakresy wartości.
Typy te przedstawia poniższa tabela.

nazwa typu

liczba bajtów

zakres od

zakres do

ograniczenia

short

2

-32768

32 767

przynajmniej 16 bitów

unsigned short

2

0

65 535

przynajmniej 16 bitów

int

4

-2 147 483 648

2 147 483 647

nie mniejsze niż typ short

unsigned int

4

0

4 294 967 295

nie mniejsze niż typ short

long

4

-2 147 483 648

2 147 483 647

przynajmniej 32 bity I nie mniejsze niż int

unsigned long

4

0

4 294 967 295

przyajmniej 32 bity I nie mniejsze niż int

long long

8

9 223 372 036 854 775 808

9 223 372 036 854 775 807

przynajmniej 64 bity I nie mniejsze niż long

unsigned long  long

8

0

18 446 744 073 709 551 615

przynajmniej 64 bity I nie mniejsze niż long

Rzeczywisty rozmiar typów danych zależy od kompilatora, jednakże musi spełniać on przedstawione w powyższej tabeli ograniczenia.
Aby sprawdzić rozmiar zmiennych na swoich maszynach należy zastosować operator sizeof. Zwróci nam on liczbę bajtów danego typu lub zmiennej.

Przykład wywołania:

int intVal = 10;
cout << "intVal: "<< sizeof intVal << endl;
cout << "int: " << sizeof(int) << endl;

 

Inicjalizowanie zmiennych.

Nadszedł czas aby pokrótce pojęcie inicjalizacji. Otóż jest to nadanie wartości początkowej dowolnemu obiektowi/zmiennej. Otóż w języku C++  można to uczynić na kilka sposobów, a oto I one:

int year = 2016;
int month(9);
int day{11};
int age = {30};
int counter{} ; //przypisanie counter wartości 0

Typy znakowe

Typ znakowy char jest również typem całkwitoliczbowym służącym do przechowywana znaków kodowanych kodem ASCII (litery, cyfry, znaki specjalne).

Inicjalizacja zmiennej typu char wygląda następująco:

char example='A';

Inicjalizując zmienną typu char, przypisujemy jej znak podany w pojedyńczym apostrofie.

W rzeczywistości, gdybyśmy zajrzeli do pamięci pod którą znajduje się zmienna example ujrzelibyśmy wartość całkowitą 65 (jest to wartość odpowiadająca literze ‚A’ w kodzie ASCII).

nazwa typu

liczba bajtów

zakres od

zakres do

char

1

-128

127

signed char

1

-128

127

unsigned char

1

0

255

wchar_t

2

0

65 535

char16_t

2

0

65 535

char32_t

4

0

4 294 967 295

W powyższej tabeli zostały przedstawione typy znakowe dostępne w C++. Na szczególną uwagę zasługują trzy ostatnie typy.

Umożliwiają one przechowywanie danych znakowych z większego zakresu niż zwykły typ char. Ze względu na to, że rozmiar typu wchar_t zależny jest od kompilatora,
postanowiono wprowadzić do języka c++ dwa dodatkowe typy o stałym ustalonym rozmiarze występujące jedynie w postaci unsigned.

Inicjalizacja zmiennych znakowych różni się w zależności od używanego typu i przedstawia się następująco:

char c1 = 'A';
wchar_t = L'A';
char16_t = u'A';
char32_t = U'A';

Liczby zmiennoprzecinkowe

Liczby zmiennoprzecinkowe, to takie które oprócz części całkowitej mogą zawierać również część ułamkową, np: -0,5; 3,14159; 7,5e12.
W przykładzie przedstawiłem dwie formy przestawiające liczby zmiennoprzcinkowe, standardową formę oraz notację naukową, w której używane jest oznaczenie ‚e’ lub ‚E’.
W przykładzie 7,5e12 oznacza pomnożenie liczby 5 przez 10 podniesione do potęgi 12.
Można również zastosować chociażby następujący opis 4,32e-5. Znaczy to tyle co pomnożenie 4.32 przez 0,00001.
W notacji naukowej wyróżniamy dwie części składowe. Mantysa to część znajdująca na lewo od oznaczenia ‚e’. Drugą składową jest wykładnik znajdujący się na prawo od oznaczenia ‚e’.

Powyższa tabela przedstawia możliwości poszczególnych typów zmiennoprzecinkowych.

nazwa typu

liczba bajtów

minimalna liczba cyfr znaczących

minimalny zakres wykładników

float

4

6-7

od -37 do 38

double

8

15-16

od -307 do 308

long double

8-9

18

od -4931 do 4932

Typ bool

Jest to ostatni I zarazem najprostszy z typów, który służy do przechowywania wartości logicznej : prawdy bądź fałszu.

nazwa typu

liczba bajtów

dopuszczalne wartości

bool

1

true,false

Przykłady:

bool isDone=false;
bool isCanceled = -100; //zmienna ma wartość true
bool isRunning = 0; //zmienna ma wartość false
bool isEnd = 1; //zmienna ma wartość true

Ciekawostka odnośnie typów bool jest to, że każda liczba może być niejawnie skonwertowana na ten typ wedle prostej reguły.Wszystkie wartości różne od zera konwertowane są na true, natomiast  na 0 false.

 

Podsumowanie

Jak widzimy ilość typów prostych jest dość spora.

Typy całkowite różnią się między sobą ilością użytych bajtów przez co zwiększają swój zakres, oraz posiadaniem znaku bądź jego znaku. Typy znakowe choć są zapisywane jako kody znakowe, to system wejścia/wyjścia prezentuje je jako odpowiednie znaki odpowiadające danemu kodowi znaku. Typy zmiennoprzecinkowe pozwalają na zapisanie części całkowitej wraz z częścią ułamkową. Dzięki formie prezentacji (mantysa I wykładnik) są one w stanie przedstawić liczbę znacznie większej niż long long przy utracie precyzji (liczba cyfr znaczących).