Сайт о телевидении

Сайт о телевидении

» » Размер типов данных c. Концепция типа данных. Какие особенности использования целочисленных типов данных

Размер типов данных c. Концепция типа данных. Какие особенности использования целочисленных типов данных

Типы данных в Си — класс данных, значения которых имеют схожие характеристики. Тип определяет внутреннее представление данных в памяти. Самые основные типы данных: логический, целочисленный, числа с плавающей точкой, строковые, указатели.

При динамической типизации переменная связывается с типом на момент инициализации. Получается, что переменная в разных участках кода может иметь разные типы. Динамическую типизацию поддерживают Java Script, Python, Ruby, PHP.

Статическая типизация является противоположностью динамической. При объявлении переменная получает тип, который не меняется в дальнейшем. Языки Си и Си++ являются именно такими. Этот способ наиболее удобный для написания сложного кода, а на стадии компиляции исключается много ошибок.

Языки неформально делятся на сильнотипизированный и слаботипизированный. Сильная типизация подразумевает, что компилятор выдаст ошибку при несовпадении ожидаемого и фактического типов.

x = 1 + “2”; //ошибка — нельзя прибавить к числу символьный знак

Пример слабой типизации.

Проверка согласования типов осуществляется системой типобезопасности. Ошибка типизации возникает, например, при попытке использовать число как функцию. Существуют нетипизированные языки. В противоположность типизированным, они позволяют осуществлять любые операции над каждым объектом.

Классы памяти

Переменные, независимо от их типа, имеют свою область видимости и время существования.

Классы памяти:

  • auto;
  • static;
  • extern;
  • register.

Все переменные в языке Си по умолчанию являются локальными. Они могут использоваться только внутри функции или блока. По завершении функции их значение уничтожается.

Статическая переменная также является локальной, но вне своего блока может иметь другое значение, а между вызовами функции значение сохраняется.

Внешняя переменная является глобальной. Она доступна в любой части кода и даже в другом файле.

Спецификаторы типов данных в Си могут не указываться в таких случаях:

  1. Все переменные внутри блока не являются переменными, соответственно, если предполагается использование именно этого класса памяти, то спецификатор auto не указывается.
  2. Все функции, объявленные вне блока или функции, являются по умолчанию глобальными, поэтому спецификатор extern не обязателен.

Для указания простых типов указываются спецификаторы int, char, float или double. К переменным могут подставляться модификаторы unsigned (беззнаковый), signed (знаковый), short, long, long long.

По умолчанию все числа являются знаковыми, соответственно, могут находиться в диапазоне только положительных чисел. Чтобы определить переменную типа char как знаковую, пишется signed char. Long, long long и short указывают, как много места в памяти отводится для хранения. Наибольшее — long long, наименьшее — short.

Char — самый маленький тип данных в Си. Для хранения значений выделяется всего 1 байт памяти. Переменной типа character обычно присваиваются символы, реже — цифры. Символьные значения берутся в кавычки.

Тип int хранит целые числа, его размер не определен — занимает до 4 байт памяти, в зависимости от архитектуры компьютера.

Явное преобразование беззнаковой переменной задается так:

Неявное выглядит так:

Float и double определяют числа с точкой. Числа float представляются в виде -2.3 или 3.34. Double используется для большей точности — после разделителя целой и дробной части указывается больше цифр. Этот тип занимает больше места в памяти, чем float.

Void имеет пустое значение. Он определяет функции, которые ничего не возвращают. С помощью этого спецификатора указывается пустое значение в аргументах методов. Указатели, которые могут принимать любой тип данных, также определяются как void.

Логический тип Bool

Применяется в проверках условий и циклах. Имеет всего два значения:

  • истина;
  • ложь.

Булевые значения могут преобразовываться в значение типа int. True эквивалентно единице, false — нулю. Преобразование типов предусмотрено только между bool и int, в противном случае компилятор выдаст ошибку.

if (x) { //Error: «Cannot implicitly convert type ‘int’ to ‘bool"»

if (x != 0) // The C# way

Строки и массивы

Массивы относятся к сложными типам даным в Си. ЯП не работает со строками так же, как это делает Джаваскрипт или Руби. В Си все строки являются массивами элементов символьного значения. Строки оканчиваются нулевым байтом “

Целый тип (int)

Размер типа int не определяется стандартом, а зависит от компьютера и компилятора.

Для 16-разрядного процессора под величины этого типа отводится 2 байта,

для 32-разрядного - 4 байта.

Спецификатор short перед именем типа указывает компилятору, что под число требуется отвести 2 байта независимо от разрядности процессора.

Спецификатор long означает, что целая величина будет занимать 4 байта.

Таким образом, на 16-разрядном компьютере эквиваленты int и short int,

а на 32-разрядном - int и long int.

Внутреннее представление величины целого типа - целое число в двоичном коде. При использовании спецификатора signed старший бит числа интерпретируется как знаковый (0 - положительное число, 1 - отрицательное). Спецификатор unsigned позволяет представлять только положительные числа, поскольку старший разряд рассматривается как часть кода числа. Т. о., диапазон значений типа int зависит от спецификаторов. Диапазоны значений величин целого типа с различными спецификаторами для IBM PC-совместимых компьютеров приведены в таблице «Диапазоны значений простых типов данных».

По умолчанию все целочисленные типы считаются знаковыми, то есть спецификатор signed можно опускать.

Константам, встречающимся в программе, приписывается тот или иной тип в соответствии с их видом. Если он по каким-либо причинам не устраивает программиста, моно явно указать требуемый тип с помощью суффиксов L, l (long) и U, u (unsigned). Например, константа 32L будет иметь тип long и занимать 4 байта. Можно использовать суффиксы L и U одновременно, например, 0x22UL или 05Lu.

Примечание. Типы short int, long int, signed int и unsigned int можно сокращать до short, long, signed и unsigned соответственно.

Символьный тип (char)

Под величину символьного типа отводится количество байт, достаточное для размещения любого символа из набора символов для данного компьютера, что и обусловило название типа. Как правило, это 1 байт. Тип char, как и другие целые типы, может быть со знаком или без знака. В величинах со знаком можно хранить значения в диапазоне от -128 до 127. При использовании спецификатора unsigned значения могут находиться в пределах от 0 до 255. Этого достаточно для хранения любого символа из 256-символьного набора ASCII. Величины типа char применяются также для хранения целых чисел.



Расширенный символьный тип (wchar_t)

Тип wchar_t предназначен для работы с набором символов, для кодировки которых недостаточно 1 байта. Например, Unicode. Размер этого типа зависит от реализации; как правило, он соответствует типу short. Строковые константы типа wchar_t записываются с префиксом L, например, L“Gates”.

Логический тип (bool)

Величины логического типа могут принимать только значения true и false , являющиеся зарезервированными словами. Внутренняя форма представления значения false - 0 (нуль). Любое другое значение интерпретируется как true. При преобразовании к целому типу true имеет значение 1.

Типы с плавающей точкой (float, double и long double)

Стандарт C++ определяет три типа данных для хранения вещественных значений: float, double и long double.

Типы данных с плавающей точкой хранятся в памяти иначе, чем целочисленные. Внутреннее представление вещественного числа состоит из двух частей - мантиссы и порядка .

В IBM PC-совместимых компьютерах величины типа float занимают 4 байта, из которых один двоичный разряд отводится под знак мантиссы , 8 разрядов под порядок и 23 под мантиссу . Мантисса - это число, большее 1.0, но меньшее 2.0. Поскольку старшая цифра мантиссы всегда равна 1, она не хранится.

Для величин типа double, занимающих 8 байт, под порядок и мантиссу отводится 11 и 52 разряда соответственно. Длина мантиссы определяет точность числа, а длина порядка - его диапазон. Как можно видеть из таблицы в конце записи, при одинаковом количестве байт, отводимом под величины типа float и long int, диапазоны их допустимых значений сильно различаются из-за внутренней формы представления .

Спецификатор long перед именем типа double указывает, что под его величину отводится 10 байт.

Константы с плавающей точкой имеют по умолчанию тип double. Можно явно указать тип константы с помощью суффиксов F, f (float) и L, l (long).

Например, константа 2E+6L будет иметь тип long double, а константа 1.82f - тип float.

При написании универсальных для разных платформ программ нельзя делать допущений о размере типа int. Для его получения необходимо пользоваться операцией sizeof, результатом которой является размер типа в байтах.

Например, для операционной системы MS-DOS sizeof (int) даст в результате 2, а для Windows 98 или OS/2 результатом будет 4.

В стандарте ANSI диапазоны значений для основных типов не задаются, определяются только соотношения между их размерами, например:

sizeof(float) ≤ slzeof(double) ≤ sizeof(long double)
sizeof(char) ≤ slzeof(short) ≤ sizeof(int) ≤ sizeof(long)

Примечание. Минимальные и максимальные допустимые значения для целых типов зависят от реализации и приведены в заголовочном файле (), характеристики вещественных типов - в файле (), а также в шаблоне класса numeric_limits

Тип void

Кроме перечисленных, к основным типам языка относится тип void, но множество значений этого типа пусто. Он используется для определения функций, которые не возвращают значения, для указания пустого списка аргументов функции, как базовый тип для указателей и в операции приведения типов.

Различные виды целых и вещественных типов, различающиеся диапазоном и точностью представления данных, введены для того, чтобы дать программисту возможность наиболее эффективно использовать возможности конкретной аппаратуры, поскольку от выбора типа зависит скорость вычислений и объем памяти. Но оптимизированная для компьютеров какого-либо одного типа программа может стать не переносимой на другие платформы, поэтому в общем случае следует избегать зависимостей от конкретных характеристик типов данных.

Тип Диапазон значений Размер (байт)
bool true и false
signed char -128 … 127
unsigned char 0 … 255
signed short int -32 768 … 32 767
unsigned short int 0 … 65 535
signed long int -2 147 483 648 … 2 147 483 647
unsigned long int 0 … 4 294 967 295
float 3.4e-38 … 3.4e+38
double 1.7e-308 … 1.7C+308
long double 3.4e-4932 … 3.4e+4932

Структура программы

Программа на языке С++ состоит из функций , описаний и директив препроцессора . Одна из функций должна иметь имя main . Выполнение программы начинается с первого оператора этой функции. Простейшее определение функции имеет следующий формат:

Как правило, функция используется для вычисления какого-либо значения, поэтому перед именем функции указывается его тип. Ниже приведены самые необходимые сведения о функциях:

  • если функция не должна возвращать значение, указывается тип void:
  • тело функции является блоком и, следовательно, заключается в фигурные скобки;
  • функции не могут быть вложенными;
  • каждый оператор заканчивается точкой с запятой (кроме составного оператора).

Пример структуры программы, содержащей функции main, fl и f2:

Программа может состоять из нескольких модулей (исходных файлов).

Замечания о вводе/выводе в C++

В языке С++ нет встроенных средств ввода/вывода - он осуществляется с помощью функций, типов и объектов, содержащихся в стандартных библиотеках.

Используется два способа: функции, унаследованные из языка С, и объекты С++.

Основные функции ввода/вывода в стиле С:

int scanf (const char* format, ...) // ввод
int printf(const char* format, ...) // вывод

Они выполняют форматированный ввод и вывод произвольного количества величин в соответствии со строкой формата format. Строка формата содержит символы, которые при выводе копируются в поток (на экран) или запрашиваются из потока (с клавиатуры) при вводе, и спецификации преобразования, начинающиеся со знака %, которые при вводе и выводе заменяются конкретными величинами.

Пример программы, использующей функции ввода/вывода в стиле С:

#include
int main() {
int i;
printf("Введите целое число\п");
scanf("%d", &i);
printf("Вы ввели число %d, спасибо!", i);
return 0;
}

Первая строка этой программы - директива препроцессора, по которой в текст программы вставляется заголовочный файл, содержащий описание использованных в программе функций ввода/вывода (в данном случае угловые скобки являются элементом языка). Все директивы препроцессора начинаются со знака #.

Третья строка - описание переменной целого типа с именем i.

Функция printf в четвертой строке выводит приглашение «Введите целое число» и переходит на новую строку в соответствии с управляющей последовательностью \n. Функция scanf заносит введенное с клавиатуры целое число в переменную i (знак & означает операцию получения адреса), а следующий оператор выводит на экран указанную в нем строку, заменив спецификацию преобразования на значение этого числа.

Программа с использованием библиотеки классов С++:

#include
int main() {
int i;
cout << "Введите целое число\n "; cin >> i;
cout << "Вы ввели число " << i << ", спасибо!";
return 0;
}

Заголовочный файл содержит описание набора классов для управления вводом/выводом. В нем определены стандартные объекты-потоки cin для ввода с клавиатуры и cout для вывода на экран, а также операции помещения в поток < < и чтения из потока >>.

Можно использовать оба способа организации ввода\вывода, но в одной программе смешивать их не рекомендуется.

Последнее обновление: 17.09.2017

Каждая переменная имеет определенный тип. И этот тип определяет, какие значения может иметь переменная, какие операции с ней можно производить и сколько байт в памяти она будет занимать. В языке C++ определены следующие базовые типы данных:

    bool : логический тип. Может принимать одну из двух значений true (истина) и false (ложь). Размер занимаемой памяти для этого типа точно не определен.

    char : представляет один символ в кодировке ASCII. Занимает в памяти 1 байт (8 бит). Может хранить любое значение из диапазона от -128 до 127, либо от 0 до 255

    signed char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от -128 до 127

    unsigned char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от 0 до 255

    wchar_t : представляет расширенный символ. На Windows занимает в памяти 2 байта (16 бит), на Linux - 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 65 535 (при 2 байтах), либо от 0 до 4 294 967 295 (для 4 байт)

    char16_t : представляет один символ в кодировке Unicode. Занимает в памяти 2 байта (16 бит). Может хранить любой значение из диапазона от 0 до 65 535

    char32_t : представляет один символ в кодировке Unicode. Занимает в памяти 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 4 294 967 295

    short : представляет целое число в диапазоне от –32768 до 32767. Занимает в памяти 2 байта (16 бит).

    Данный тип также имеет синонимы short int , signed short int , signed short .

    unsigned short : представляет целое число в диапазоне от 0 до 65535. Занимает в памяти 2 байта (16 бит).

    Данный тип также имеет синоним unsigned short int .

    int : представляет целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита). Диапазон предельных значений соответственно также может варьироваться от –32768 до 32767 (при 2 байтах) или от −2 147 483 648 до 2 147 483 647 (при 4 байтах). Но в любом случае размер должен быть больше или равен размеру типа short и меньше или равен размеру типа long

    Данный тип имеет синонимы signed int и signed .

    unsigned int : представляет положительное целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита), и из-за этого диапазон предельных значений может меняться: от 0 до 65535 (для 2 байт), либо от 0 до 4 294 967 295 (для 4 байт).

    В качестве синонима этого типа может использоваться unsigned

    long : представляет целое число в диапазоне от −2 147 483 648 до 2 147 483 647. Занимает в памяти 4 байта (32 бита).

    У данного типа также есть синонимы long int , signed long int и signed long

    unsigned long : представляет целое число в диапазоне от 0 до 4 294 967 295. Занимает в памяти 4 байта (32 бита).

    Имеет синоним unsigned long int .

    long long : представляет целое число в диапазоне от −9 223 372 036 854 775 808 до +9 223 372 036 854 775 807. Занимает в памяти, как правило, 8 байт (64 бита).

    Имеет синонимы long long int , signed long long int и signed long long .

    unsigned long long : представляет целое число в диапазоне от 0 до 18 446 744 073 709 551 615. Занимает в памяти, как правило, 8 байт (64 бита).

    Имеет синоним unsigned long long int .

    float : представляет вещественное число ординарной точности с плавающей точкой в диапазоне +/- 3.4E-38 до 3.4E+38. В памяти занимает 4 байта (32 бита)

    double : представляет вещественное число двойной точности с плавающей точкой в диапазоне +/- 1.7E-308 до 1.7E+308. В памяти занимает 8 байт (64 бита)

    long double : представляет вещественное число двойной точности с плавающей точкой не менее 8 байт (64 бит). В зависимости от размера занимаемой памяти может отличаться диапазон допустимых значений.

    void : тип без значения

Таким образом, все типы данных за исключением void могут быть разделены на три группы: символьные (char, wchar_t, char16_t, char32_t), целочисленные (short, int, long, long long) и типы чисел с плавающей точкой (float, double, long double).

Символьные типы

Для представления символов в приложении используются типы char , wchar_t , char16_t и char32_t .

Определим несколько переменных:

Char c ="d"; wchar_t d ="c";

Переменная типа char в качестве значения принимает один символ в одинарных кавычках: char c ="d" . Также можно присвоить число из указанного выше в списке диапазона: char c = 120 . В этом случае значением переменной c будет тот символ, который имеет код 120 в таблице символов ASCII.

Стоит учитывать, что для вывода на консоль символов wchar_t следует использовать не std::cout, а поток std::wcout :

#include int main() { char a = "H"; wchar_t b = "e"; std::wcout << a << b << "\n"; return 0; }

При этом поток std::wcout может работать как с char, так и с wchar_t. А поток std::cout для переменной wchar_t вместо символа будет выводить его числовой код.

В стандарте С++11 были добавлены типы char16_t и char32_t , которые ориентированы на использование Unicode. Однако на уровне ОС пока не реализованы потоки для работы с этими типами. Поэтому если потребуется вывести на консоль значения переменных этих типов, то необходимо преобразовать переменные к типам char или wchar_t:

#include int main() { char a = "H"; wchar_t b = "e"; char16_t c = "l"; char32_t d = "o"; std::cout << a << (char)b << (char)c << (char)d << "\n"; return 0; }

В данном случае при выводе перед переменными указывается операция приведения к типу char - (char) , благодаря чему значения переменных b, c и d преобразуются в тип char и могут быть выведены на консоль с помощью потока std::cout.

Целочисленные типы

Целочисленные типы представлены следующими типами: short , unsigned short , int , unsigned int , long , unsigned long , long long и unsigned long long :

Short a = -10; unsigned short b= 10; int c = -30; unsigned int d = 60; long e = -170; unsigned long f = 45; long long g = 89;

Типы чисел с плавающей точкой

Типы чисел с плавающей точкой иили дробные числа представлены такими типами как float , double и long double :

Float a = -10.45; double b = 0.00105; long double c = 30.890045;

Размеры типов данных

В выше приведенном списке для каждого типа указан размер, который он занимает в памяти. Однако стоит отметить, что предельные размеры для типов разработчики компиляторов могут выбирать самостоятельно, исходя из аппаратных возможностей компьютера. Стандарт устанавливает лишь минимальные значения, которые должны быть. Например, для типов int и short минимальное значение - 16 бит, для типа long - 32 бита, для типа long double. При этом размер типа long должен быть не меньше размера типа int, а размер типа int - не меньше размера типа short, а размер типа long double должен быть больше double. К примеру, компилятор g++ под Windows для long double использует 12 байт, а компилятор, встроенный в Visual Studio и также работающий под Windows, для long double использует 8 байт. То есть даже в рамках одной платформы разные компиляторы могут по разному подходить к размерам некоторых типов данных. Но в целом используются те размеры, которые указаны выше при описании типов данных.

Однако бывают ситуации, когда необходимо точно знать размер определенного типа. И для этого в С++ есть оператор sizeof() , который возвращает размер памяти в байтах, которую занимает переменная:

#include int main() { long double number = 2; std::cout << "sizeof(number) =" << sizeof(number); return 0; }

Консольный вывод при компиляции в g++:

sizeof(number) = 12

При этом при определении переменных важно понимать, что значение переменной не должно выходить за те пределы, которые очерчены для ее типа. Например:

Unsigned short number = -65535;

Компилятор G++ при компиляции программы с этой строкой выдаст ошибку о том, что значение -65535 не входит в диапазон допустимых значений для типа unsigned short и будет усечено.

В Visual Studio компиляция может пройти без ошибок, однако при этом переменная number получит значение 2 - результат преобразования числа -65535 к типу unsigned short. То есть опять же результат будет не совсем тот, который ожидается. Значение переменной - это всего лишь набор битов в памяти, которые интерпретируются в соответствии с определенным типом. И для разных типов один и тот же набор битов может интерпретироваться по разному. Поэтому важно учитывать диапазоны значений для того или иного типа при присвоении переменной значения.

Спецификатор auto

Иногда бывает трудно определить тип выражения. И согласно последним стандартам можно предоставить компилятору самому выводить тип объекта. И для этого применяется спецификатор auto . При этом если мы определяем переменную со спецификатором auto, эта переменная должна быть обязательно инициализирована каким-либо значением:

Auto number = 5;

На основании присвоенного значения компилятор выведет тип переменной. Неинициализированные переменные со спецификатором auto не допускаются.

Типом данных в программировании называют совокупность двух множеств: множество значений и множество операций, которые можно применять к ним. Например, к типу данных целых неотрицательных чисел, состоящего из конечного множества натуральных чисел, можно применить операции сложения (+), умножения (*), целочисленного деления (/), нахождения остатка (%) и вычитания (−).

Язык программирования, как правило, имеет набор примитивных типов данных - типы, предоставляемые языком программирования как базовая встроенная единица. В C++ такие типы создатель языка называет фундаментальными типами . Фундаментальными типами в C++ считаются:

  • логический (bool);
  • символьный (напр., char);
  • целый (напр., int);
  • с плавающей точкой (напр., float);
  • перечисления (определяется программистом);
  • void .

Поверх перечисленных строятся следующие типы:

  • указательные (напр., int*);
  • массивы (напр., char);
  • ссылочные (напр., double&);
  • другие структуры.

Перейдём к понятию литерала (напр., 1, 2.4F, 25e-4, ‘a’ и др.): литерал - запись в исходном коде программы, представляющаясобой фиксированное значение. Другими словами, литерал - это просто отображение объекта (значение) какого-либо типа в коде программы. В C++ есть возможность записи целочисленных значений, значений с плавающей точкой, символьных, булевых, строковых.

Литерал целого типа можно записать в:

  • 10-й системе счисления. Например, 1205 ;
  • 8-й системе счисления в формате 0 + число. Например, 0142 ;
  • 16-й системе счисления в формате 0x + число. Например, 0x2F .

24, 030, 0x18 - это всё записи одного и того же числа в разных системах счисления.
Для записи чисел с плавающей точкой используют запись через точку: 0.1, .5, 4. - либо в
экспоненциальной записи - 25e-100. Пробелов в такой записи быть не должно.

Имя, с которым мы можем связать записанные литералами значения, называют переменной. Переменная - это поименованная либо адресуемая иным способом область памяти, адрес которой можно использовать для доступа к данным. Эти данные записываются, переписываются и стираются в памяти определённым образом во время выполнения программы. Переменная позволяет в любой момент времени получить доступ к данным и при необходимости изменить их. Данные, которые можно получить по имени переменной, называют значением переменной.
Для того, чтобы использовать в программе переменную, её обязательно нужно объявить, а при необходимости можно определить (= инициализировать). Объявление переменной в тексте программы обязательно содержит 2 части: базовый тип и декларатор. Спецификатор и инициализатор являются необязательными частями:

Const int example = 3; // здесь const - спецификатор // int - базовый тип // example - имя переменной // = 3 - инициализатор.

Имя переменной является последовательностью символов из букв латинского алфавита (строчных и прописных), цифр и/или знака подчёркивания, однако первый символ цифрой быть не может . Имя переменной следует выбирать таким, чтобы всегда было легко догадаться о том, что она хранит, например, «monthPayment». В конспекте и на практиках мы будем использовать для правил записи переменных нотацию CamelCase. Имя переменной не может совпадать с зарезервированными в языке словами, примеры таких слов: if, while, function, goto, switch и др.

Декларатор кроме имени переменной может содержать дополнительные символы:

  • * - указатель; перед именем;
  • *const - константный указатель; перед именем;
  • & - ссылка; перед именем;
  • - массив; после имени;
  • () - функция; после имени.

Инициализатор позволяет определить для переменной её значение сразу после объявления. Инициализатор начинается с литерала равенства (=) и далее происходит процесс задания значения переменной. Вообще говоря, знак равенства в C++ обозначает операцию присваивания; с её помощью можно задавать и изменять значение переменной. Для разных типов он может быть разным.

Спецификатор задаёт дополнительные атрибуты, отличные от типа. Приведённый в примере спецификатор const позволяет запретить последующее изменение значение переменной. Такие неизменяемые переменные называют константными или константой.

Объявить константу без инициализации не получится по логичным причинам:

Const int EMPTY_CONST; // ошибка, не инициализована константная переменная const int EXAMPLE = 2; // константа со значением 2 EXAMPLE = 3; // ошибка, попытка присвоить значение константной переменной

Для именования констант принято использовать только прописные буквы, разделяя слова символом нижнего подчёркивания.

Основные типы данных в C++

Разбирая каждый тип, читатель не должен забывать об определении типа данных.

1. Целочисленный тип (char, short (int), int, long (int), long long)

Из названия легко понять, что множество значений состоит из целых чисел. Также множество значений каждого из перечисленных типов может быть знаковым (signed) или беззнаковым (unsigned). Количество элементов, содержащееся в множестве, зависит от размера памяти, которая используется для хранения значения этого типа. Например, для переменной типа char отводится 1 байт памяти, поэтому всего элементов будет:

  • 2 8N = 2 8 * 1 = 256, где N - размер памяти в байтах для хранения значения

В таком случае диапазоны доступных целых чисел следующие:

  • - для беззнакового char
  • [-128..127] - для знакового char

По умолчанию переменная целого типа считается знаковой. Чтобы указать в коде, что переменная должна быть беззнаковой, к базовому типу слева приписывают признак знаковости, т.е. unsigned:

Unsigned long values; // задаёт целый (длинный) беззнаковый тип.

Перечисленные типы отличаются только размерами памяти, которая требуется для хранения. Поскольку язык C++ достаточно машинно-зависимый стандарт языка лишь гарантирует выполнение следующего условия:

  • 1 = размер char ≤ размер short ≤ размер int ≤ размер long.

Обычно размеры типов следующие: char - 1, short - 2, int - 4, long -8, long long - 8 байт.

Со значениями целого типа можно совершать арифметические операции: +, -, *, /, %; операции сравнения: ==, !=, <=, <, >, >=; битовые операции: &, |, xor, <<, >>.
Большинство операций, таких как сложение, умножение, вычитание и операции сравнения, не вызывают проблем в понимании. Иногда, после выполнения арифметических операций, результат может оказаться за пределами диапазона значений; в этом случае программа выдаст ошибку.
Целочисленное деление (/) находит целую часть от деления одного целого числа, на другое. Например:

  • 6 / 4 = 1;
  • 2 / 5 = 0;
  • 8 / 2 = 4.

Символ процента (%) обозначает операцию определение остатка от деления двух целых чисел:

  • 6 % 4 = 2;
  • 10 % 3 = 1.

Более сложные для понимания операции - битовые: & (И), | (ИЛИ), xor (исключающее ИЛИ), << (побитовый сдвиг влево), >> (побитовый сдвиг вправо).

Битовые операции И, ИЛИ и XOR к каждому биту информации применяют соответствующую логическую операцию:

  • 1 10 = 01 2
  • 3 10 = 11 2
  • 1 10 & 3 10 = 01 2 & 11 2 = 01 2
  • 1 10 | 3 10 = 01 2 | 11 2 = 11 2
  • 1 10 xor 3 10 = 01 2 xor 11 2 = 10 2

В обработке изображения используют 3 канала для цвета: красный, синий и зелёный - плюс прозрачность, которые хранятся в переменной типа int, т.к. каждый канал имеет диапазон значений от 0 до 255. В 16-иричной системе счисления некоторое значение записывается следующим образом: 0x180013FF; тогда значение 18 16 соответствует красному каналу, 00 16 - синему, 13 16 - зелёному, FF - альфа-каналу (прозрачности). Чтобы выделить из такого целого числа определённый канал используют т.н. маску, где на интересующих нас позициях стоят F 16 или 1 2 . Т.е., чтобы выделить значение синего канала необходимо использовать маску, т.е. побитовое И:

Int blue_channel = 0x180013FF & 0x00FF0000;

После чего полученное значение сдвигается вправо на необходимое число бит.

Побитовый сдвиг смещает влево или вправо на столько двоичных разрядов числа, сколько указано в правой части операции. Например, число 39 для типа char в двоичном виде записывается в следующем виде: 00100111. Тогда:

Char binaryExample = 39; // 00100111 char result = binaryExample << 2; // сдвигаем 2 бита влево, результат: 10011100

Если переменная беззнакового типа, тогда результатом будет число 156, для знакового оно равно -100. Отметим, что для знаковых целых типов единица в старшем разряде битового представления - признак отрицательности числа. При этом значение, в двоичном виде состоящие из всех единиц соответствует -1; если же 1 только в старшем разряде, а в остальных разрядах - нули, тогда такое число имеет минимальное для конкретного типа значения: для char это -128.

2. Тип с плавающей точкой (float, double (float))

Множество значений типа с плавающей точкой является подмножеством вещественных чисел, но не каждое вещественное число представимо в двоичном виде, что приводит иногда к глупым ошибкам:

Float value = 0.2; value == 0.2; // ошибка, value здесь не будет равно 0.2.

Работая с переменными с плавающей точкой, программист не должен использовать операцию проверки на равенство или неравенство, вместо этого обычно используют проверку на попадание в определённый интервал:

Value - 0.2 < 1e-6; // ok, подбирать интервал тоже нужно осторожно

Помимо операций сравнения тип с плавающей точкой поддерживает 4 арифметические операции, которые полностью соответствуют математическим операциям с вещественными числами.

3. Булевый (логический) тип (bool)

Состоит всего из двух значений: true (правда) и false (ложь). Для работы с переменными данного типа используют логические операции: ! (НЕ), == (равенство), != (неравенство), && (логическое И), || (логическое ИЛИ). Результат каждой операции можно найти в соответствующей таблицы истинности. например:

X Y XOR 0 0 0 0 1 1 1 0 1 1 1 0

4. Символьный тип (char, wchar_t)

Тип char - не только целый тип (обычно, такой тип называют byte), но и символьный, хранящий номер символа из таблицы символом ASCII . Например код 0x41 соответствует символу ‘A’, а 0x71 - ‘t’.

Иногда возникает необходимость использования символов, которые не закреплены в таблицы ASCII и поэтому требует для хранения более 1-го байта. Для них существует широкий символ (wchar_t).

5.1. Массивы

Массивы позволяют хранить последовательный набор однотипных элементов. Массив хранится в памяти непрерывным блоком, поэтому нельзя объявить массив, не указав его размер . Чтобы объявить массив после имени переменной пишут квадратные скобки () с указанием его размера. Например:

Int myArray; // Массив из 5-и элементов целого типа

Для инициализации массива значения перечисляют в фигурных скобках. Инициализировать таким образом можно только во время объявления переменной. Кстати, в этом случае необязательно указывать размер массива:

Int odds = {1, 3, 7, 9, 11}; // Массив инициализируется 5-ю значениями

Для доступа к определённому значению в массиве (элемента массива) используют операцию доступа по индексу () с указанием номера элемента (номера начинаются с 0). Например:

Odds; // доступ к первому элементу массива. Вернёт значение 1 odds; // доступ к третьему элементу. Вернёт значение 7 odds = 13; // 5-му элементу массива присваиваем новое значение odds; // ошибка доступа

5.3. Строки

Для записи строки программисты используют идею, что строка - последовательный ряд (массив) символов. Для идентификации конца строки используют специальный символ конца строки: ‘\0’. Такие специальные символы, состоящие из обратного слэша и идентифицирующего символа, называют управляющими или escape-символами. Ещё существуют, например, ‘\n’ - начало новой строки, ‘\t’ - табуляция. Для записи в строке обратного слэша применяют экранирование - перед самим знаком ставят ещё один слэш: ‘\’. Экранирование также применяют для записи кавычек.

Создадим переменную строки:

Char textExample = {‘T’, ‘e’, ‘s’, ‘t’, ‘\0’}; // записана строка «Test»

Существует упрощённая запись инициализации строки:

Char textExample = “Test”; // Последний символ не пишется, но размер всё ещё 5

Не вдаваясь в подробности, приведём ещё один полезный тип данных - string. Строки
такого типа можно, например, складывать:

String hello = "Привет, "; string name = "Макс!"; string hello_name = hello + name; // Получится строка «Привет, Макс!»

6. Ссылка

Int a = 2; // переменная «a» указывает на значение 2 int &b = a; // переменная «b» указывает туда же, куда и «a» b = 4; // меняя значение b, программист меняет значение a. Теперь a = 4 int &c = 4; // ошибка, так делать нельзя, т.к. ссылка нельзя присвоить значение

7. Указатель

Чтобы разобраться с этим типом данных, необходимо запомнить, что множество значений этого типа - адреса ячеек памяти, откуда начинаются данные. Также указатель поддерживает операции сложения (+), вычитания (-) и разыменовывания (*).

Адреса 0x0 означает, что указатель пуст, т.е. не указывает ни на какие данные. Этот адрес имеет свой литерал - NULL:

Int *nullPtr = NULL; // пустой указатель

Сложение и вычитание адреса с целым числом или другим адресом позволяет
передвигаться по памяти, доступной программе.

Операция получения данных, начинающихся по адресу, хранящемуся в указателе, называется разыменовывания (*). Программа считывает необходимое количество ячеек памяти и возвращает значение, хранимое в памяти.

Int valueInMemory = 2; // задаём переменну целого типа int *somePtr = &valueIntMemory; // копируем адрес переменной, здесь & - возвращает адрес переменной somePtr; // адрес ячейки памяти, например, 0x2F *somePtr; // значение хранится в 4-х ячейках: 0x2F, 0x30, 0x31 и 0x32

Для указателей не доступна операция присваивания, которая синтаксически совпадает с операцией копирования. Другими словами, можно скопировать адрес другого указателя или адрес переменной, но определить значение адреса самому нельзя.

Сам указатель хранится в памяти, как и значения переменных других типов, и занимает 4 байта, поэтому можно создать указатель на указатель.

8. Перечисления

Перечисления единственный базовый тип, задаваемый программистом. По большому счёту перечисление - упорядоченный набор именованных целочисленных констант, при этом имя перечисления будет базовым типом.

Enum color {RED, BLUE, GREEN};

По умолчанию, RED = 0, BLUE = 1, GREEN = 2. Поэтому значения можно сравнивать между собой, т.е. RED < BLUE < GREEN. Программист при объявлении перечисления может самостоятельно задать значения каждой из констант:

Enum access {READ = 1, WRITE = 2, EXEC = 4};

Часто удобно использовать перечисления, значения которых являются степенью двойки, т.к. в двоичном представлении число, являющееся степенью 2-и, будет состоять из 1-й единицы и нулей. Например:

8 10 = 00001000 2

Результат сложения этих чисел между собой всегда однозначно указывает на то, какие числа складывались:

37 10 = 00100101 2 = 00000001 2 + 00000100 2 + 00100000 2 = 1 10 + 4 10 + 32 10

Void

Синтаксически тип void относится к фундаментальным типам, но использовать его можно лишь как часть более сложных типов, т.к. объектов типа void не существует. Как правило, этот тип используется для информирования о том, что у функции нет возвращаемого значения либо в качестве базового типа указателя на объекты неопределённых типов:

Void object; // ошибка, не существует объектов типа void void &reference; // ошибка, не существует ссылов на void void *ptr; // ok, храним указатель на неизвестный тип

Часто мы будем использовать void именно для обозначения того, что функция не возвращает никакого значения. С указателем типа void работают, когда программист берёт полностью на себя заботу о целостности памяти и правильном приведении типа.

Приведение типов

Часто бывает необходимо привести значение переменной одного типа к другому. В случае, когда множество значений исходного типа является подмножеством большего типа (например, int является подмножеством long, а long - double), компилятор способен неявно (implicitly ) изменить тип значения.

Int integer = 2; float floating = integer; // floating = 2.0

Обратное приведение типа будет выполнено с потерей информации, так от числа с плавающей точкой останется только целая часть, дробная будет потеряна.

Существует возможность явного (explicitly) преобразования типов, для этого слева от переменной или какого-либо значения исходного типа в круглых скобках пишут тип, к которому будет произведено приведение:

Int value = (int) 2.5;

Унарные и бинарные операции

Те операции, которые мы выполняли ранее, называют бинарными: слева и справа от символа операции находятся значения или переменные, например, 2 + 3. В языках программирования помимо бинарных операций также используют унарные операции, которые применяются к переменным. Они могу находится как слева, так и справа от переменной, несколько таких операций встречались ранее - операция разыменовывания (*) и взятие адреса переменной (&) являются унарными. Операторы «++» и «—» увеличивают и уменьшают значение целочисленной переменной на 1 соответственно, причём могу писаться либо слева, либо справа от переменной.

В C++ также применяется сокращённая запись бинарных операций на тот случай, когда в левой и правой частях выражения находится одна и та же переменная, т.е. выполняется какая-либо операция со значением переменной и результат операции заносится в ту же переменную:

A += 2; // то же самое, что и a = a + 2; b /= 5; // то же самое, что и b = b / 5; c &= 3; // то же самое, что и c = c & 3;

Ответ:
  1. Целочисельные типы данных:

short int , unsigned short int , int , unsigned int , long , unsigned long .

  1. Типы данных с плавающей запятой (соответствуют вещественным типам):

float , double , long double .

  1. Символьный тип данных:

char (signed char ), unsigned char, wchar_t .

  1. Логический тип данных:

bool .

  1. Перечислимый тип данных (введен в Visual C++ ):

enum .

2. Какие особенности использования целочисленных типов данных?

В C++ основные целочисленные типы данных: short int , unsigned short int , int , unsigned int , long (long int ), unsigned long (unsigned long int ).

Эти типы данных представляют значения из множества целых чисел. Например:

2 -100 398

Типы данных, которые начинаются из приставки unsigned , могут содержать только положительные числа.

Данные типа short int , unsigned short int занимают в два раза меньше места в памяти чем данные типа int , unsigned int .

Данные типа long , unsigned long занимают в два раза больше места в памяти чем данные типа int , unsigned int .

3. Как в программе описать переменную с именем x целого типа?

Ответ:
int x; // целое со знаком

В результате под переменную x будет выделено место в памяти размером 4 байта. Размер памяти, которая выделяется под переменную зависит от характеристик компьютера, типа операционной системы и настроек компилятора.

4. Как в переменную целого типа записать число 239?

Для этого используется оператор присваивания, который обозначается символом ‘= ‘.

Ответ 1. Внесение числа в переменную после ее описания.

int x; x = 239;

Ответ 2. Внесение числа в переменную во время ее описания (начальная инициализация).

int x = 239;

5. Какие особенности типов данных с плавающей запятой?

Типы данных с плавающей запятой разрешают представлять значения из множества вещественных чисел. Например:

8.35 -990.399 239.0.

В C++ есть следующие базовые типы данных с плавающей запятой:

float , double , long double .

Переменная типа double занимает в 2 раза больше места в памяти компьютера чем переменная типа float .

Так же переменная типа long double занимает в 2 раза больше места в памяти компьютера, чем переменная типа double .

6. Как описать переменную, которая принимает значение с плавающей запятой?

Пример описания переменных типа float , double , long double :

float f; double d; long double ld;

7. Как в переменную с плавающей запятой записать числовые значения?

Пример внесения числовых данных в переменные типы с плавающей запятой:

float f = -9928.45; // начальная инициализация double d; long double ld; d = 0.445332; // оператор присваивания ld = 3892923898239.030903; // оператор присваивания

8. Как перевести переменную типа float в тип int ?

Для этого используется операция приведения типов. В скобках нужно указать название типа к которому происходит приведение.

float a; int b; a = 8.457; b = (int ) a; // b = 8

При использовании операций приведения типов, нужно учитывать ограничения, которые накладываются на типы, которые занимают меньше места в памяти компьютера.

Например, переменная типа short int может представлять меньший диапазон чисел, чем переменные типов float , double . В следующему листинге происходит переполнение значения в переменной типа short int :

short int i; float f; f = 3990099.8; i = (int )f; // i = -7597 - переполнение

9. Как перевести переменную из типа int в тип double ?

Пример приведения с int в double :

int i; double d; i = 982; d = (double )i; // d = 982.0

10. Какие особенности использования данных типа char (символьных данных) в программе?

Данные типа char представляют символьное значение кода, введенного с клавиатуры. Код символа есть целое число.

Например, код символа ‘f’ равен значению 102 .

Фрагмент кода, в котором вычисляется код символа:

int code; char symbol; symbol = "f" ; code = (int )symbol; // code = 102

Данные типа char есть теми же целыми числами. Данные типа char занимают в памяти компьютера 1 байт.

Соотношение «символ-код» размещается в таблице символов Windows. Символы с кодами от 0 до 127 – это зарезервированные символы BIOS. Они включают наиболее употребляемые символы, символы цифр, символы латинской азбуки. Эти символы изменить нельзя.

Символы с кодами от 128 до 255 – это региональные символы, которые привязанные к конкретной азбуке того компьютера на котором установленная операционная система Windows.

11. Какие особенности использования данных типа bool (логический тип)?

Переменные типа bool могут принимать только два значения:

true – истина,

false – ложь.

Эти переменные используются для проверки логических выражений. Числовое значение true равно 1 . Числовое значение false равно 0 .

Фрагмент кода, который определяет числовые значения true и false :

int result; bool b; result = (int )true ; // result = 1 b = false ; result = (int )b; // result = 0

Фрагмент кода, который превращает типы int и float в bool :

int i; float f; bool b; i = 6; b = (bool )i; // b = True f = 0.0; b = (bool )f; // b = False

12. Как определить размер памяти, который занимает переменная данного типа?

Для этого используется операция sizeof() .

Фрагмент кода, который определяет размер некоторых типов данных:

int d; d = sizeof (char ); // d = 1 d = sizeof (unsigned int ); // d = 4 d = sizeof (float ); // d = 4 d = sizeof (double ); // d = 8

13. Каким образом осуществляется инициализация переменных разных типов?

int d = 28; float z = (float )2.85; char c = "k" ; String ^s = "Hello!" ; double r = -8.559;

14. Каким образом определить максимально допустимое (минимально допустимое) значение переменной определенного типа?

Чтобы определить максимально допустимое или минимально допустимое значение переменной некоторого типа в библиотеке .NET Framework используются свойства MaxValue и MinValue .

Примеры определения предельных значений переменных разных типов.

Для переменных типа int :

// тип int int i; long MaxInt; long MinInt; MaxInt = (long )i.MaxValue; // MaxInt = 2147483647 MinInt = (long )i.MinValue; // MinInt = -2147483648

Для переменных типа short int :

// тип short int short int si; int MaxInt; int MinInt; MaxInt = (int )si.MaxValue; // MaxInt = 32767 MinInt = (int )si.MinValue; // MinInt = -32768

Для переменных типа unsigned int :

// тип unsigned int unsigned int ui; unsigned int MaxInt; unsigned int MinInt; MaxInt = ui.MaxValue; // MaxInt = 4294967295 MinInt = ui.MinValue; // MinInt = 0

Для переменных типа float :

// тип float float f; float MaxF; float MinF; MaxF = f.MaxValue; // MaxF = 3.402823E+38 MinF = f.MinValue; // MinF = -3.402823E+38

Для переменных типа double :

// тип double double d; double MaxD; double MinD; Max = d.MaxValue; // Max = 1.79769313486232E+308 Min = d.MinValue; // Min = -1.79769313486232E+308

Для переменных типа char :

// тип char char c; int MaxC; int MinC; Max = (int )c.MaxValue; // Max = 127 Min = (int )c.MinValue; // Min = -128

15. Какие особенности использования типа enum ?

Тип enum – это перечислительный тип данных. В нем задаются мнемонические значения для множеств целых значений. Каждое мнемоническое значение имеет определенное содержание и представляется целым числом.

Пример использования типа enum для обозначения месяцев года:

enum months { January, February, March, April, May, June, July, August, September, October, November, December } mn; mn = January; // mn = 0 mn = March; // mn = 2 mn = September; // mn = 8

В приведенном примере описывается переменная с именем mn типа enum months . Мнемонические значения месяцев (January , February , …) начинаются с 0 (0 , 1 , 2 , …). Мнемоническому значению January соответствует целое значение 0 , мнемоническому значению February соответствует целое значение 1 , и т.д.

Итак, с помощью типа enum , в тексте программы можно использовать мнемонические обозначения для лучшей наглядности исходного кода.

Можно написать и так:

mn = (enum months)2; // mn = March mn = (enum months)11; // mn = December

16. Какие особенности применения типа void в программах на C ++ ?

Тип данных void используется в следующих случаях:

  • если нужно описать функцию, которая не возвращает никакого значения (см. пример);
  • если нужно описать функцию, которая не получает параметров (см. пример).

Пример . Функция MyFun() без параметров, которая не возвращает никакого значения (возвращает тип void ) и не получает параметров.

public : void MyFun(void ) { // тело функции // ... return; // возврат из функции, которая не возвращает значения } // вызов функции из программы ... MyFun(); ...

17. Можно ли объявлять переменную типа void в программе?

Нельзя, так как тип void не связан со значением.

Объявление переменной типа void приводит к ошибке компиляции с выводом сообщения:

"Illegal use of type void "

18. Какие особенности применения типа wchar _ t в Visual C ++ ?

Переменные типа char (смотрите предыдущие пункты) используются для сохранения 8-разрядных ASCII -символов.

Тип wchar_t используется для сохранения символов, которые входят в состав больших символьных наборов. Например, в китайской азбуке есть огромное количество символов. 8 разрядов недостаточно, чтобы представить весь набор символов китайской азбуки. Поэтому, если нужно использовать программу на международном рынке, целесообразно заменить тип char на wchar_t .

Пример использования типа wchar_t .

... wchar_t t; // для переменной t выделяется 2 байта памяти t = "s"; ...