Основы языка Си: структура Си-программы, базовые типы и конструирование новых типов, операции и выражения
Типы переменных
При рассмотрении типов переменных в Си и C++ следует различать понятия базового типа и конструкции, позволяющей строить новые типы на основе уже построенных. Базовых типов совсем немного - это целые и вещественные числа, которые могут различаться по диапазону возможных значений (или по длине в байтах) и, в случае языка C++, логический тип. К конструкциям относятся массив, указатель и структура, а также класс в C++.
Базовые типы
В языке Си используются всего два базовых типа: целые и вещественные числа. Кроме того, имеется фиктивный тип void ("пустота"), который применяется либо для функции, не возвращающей никакого значения, либо для описания указателя общего типа (когда неизвестна информация о типе объекта, на который ссылается указатель).
В C++ добавлен логический тип.
Целочисленные типы
Целочисленные типы различаются по длине в байтах и по наличию знака. Их четыре - char, short, int и long. Кроме того, к описанию можно добавлять модификаторы unsigned или signed для беззнаковых (неотрицательных) или знаковых целых чисел.
Тип int
Самый естественный целочисленный тип - это тип int, от слова integer - целое число. Тип int всегда соответствует размеру машинного слова или адреса. Все действия с элементами типа int производятся максимально быстро. Всегда следует выбирать именно тип int, если использование других целочисленных типов не диктуется явно спецификой решаемой задачи. Параметры большинства стандартных функций, работающих с целыми числами или символами, имеют тип int. Целочисленные типы были подробно рассмотрены в "лекции 2" . Подчеркнем еще раз, что целочисленные переменные хранят на самом деле не целые числа, а элементы кольца вычетов по модулю m, где m - степень двойки.
В современных архитектурах элемент типа int занимает 4 байта, т.е. m = 232. Элементы типа int трактуются в Си как числа со знаком. Минимальное отрицательное число равно -231 = -2147483648, максимальное положительное равно 231-1 = 2147483647.
При описании переменной сначала указывается базовый тип, затем - имя переменной или список имен, разделенных запятыми, например,
int x; int y, z, t;
При описании переменных можно присваивать им начальные значения:
int maxind = 1000; int a = 5, b = 7;
Кроме типа int, существуют еще три целочисленных типа: char, short и long.
Тип char
Тип char представляет целые числа в диапазоне от -128 до 127. Элементы типа char занимают один байт памяти. Слово " char " является сокращением от character, что в переводе означает "символ". Действительно, традиционно символы представляются их целочисленными кодами, а код символа занимает один байт (см. лекцию 3). Тем не менее, подчеркнем, что элементы типа char - это именно целые числа, с ними можно выполнять все арифметические операции. С математической точки зрения, элементы типа char - это элементы кольца вычетов m = Z256. Стандарт Си не устанавливает, трактуются ли элементы типа char как знаковые или беззнаковые числа, но большинство Си-компиляторов считают char знаковым типом. Примеры описаний переменных типа char:
char c; char eof = (-1); char letterA = 'A';
В последнем случае значение переменной " letterA " инициализируется кодом латинской буквы 'A', т.е. целым числом 65. В Си символьные константы записываются в одинарных апострофах и означают коды соответствующих символов в кодировке ASCII. Рассмотрим следующий пример:
char c = 0; char d = '0';
Здесь переменная c инициализируется нулевым значением, а переменная d - значением 48, поскольку символ '0' имеет код 48.
Типы short и long
Слова short и long означают в Си короткое и длинное целое число со знаком. Стандарт Си не устанавливает конкретных размеров для типов short и long. В самой распространенной в настоящее время 32-разрядной архитектуре переменная типа short занимает 2 байта (диапазон значений - от -32768 до 32767 ), а тип long совпадает с типом int, размер его равен четырем байтам. Примеры описаний:
short s = 30000; long x = 100000; int y = 100000;
В 32-разрядной архитектуре переменные x и y имеют один и тот же тип.
Модификатор unsigned
Типы int, short и long представляют целые числа со знаком. Для типа char стандарт Си не устанавливает явно наличие знака, однако большинство компиляторов трактуют элементы типа char как целые числа со знаком в диапазоне от -128 до 127. Если необходимо трактовать целые числа как неотрицательные, или беззнаковые, следует добавить модификатор unsigned при описании переменных. Примеры:
unsigned char c = 255; unsigned short s = 65535; unsigned int i = 1000000000; unsigned j = 1;
При описании типа " unsigned int " слово " int " можно опускать, что и сделано в последнем примере.
Следует по возможности избегать беззнаковых типов, поскольку арифметика беззнаковых чисел не на всех компьютерах реализована одинаково и из-за этого при переносе программы с одной платформы на другую могут возникнуть проблемы. По этой причине в языке Java беззнаковые числа запрещены.
Имеется также модификатор signed (знаковый). Его имеет смысл использовать на тех платформах, в которых тип char является беззнаковым. Пример описания:
signed char d = (-1);
Вещественные типы
Вещественных типов два: длинное вещественное число double (переводится как "двойная точность") и короткое вещественное число float (переводится как "плавающее"). Вещественные типы были подробно рассмотрены в разделе 1.4.2. Вещественное число типа double занимает 8 байтов, типа float - 4 байта.
Тип double является основным для компьютера. Тип float - это, скорее, атавизм, оставшийся от ранних версий языка Си. Компьютер умеет производить арифметические действия только с элементами типа double, элементы типа float приходится сначала преобразовывать к double. Точность, которую обеспечивает тип float, низка и не достаточна для большинства практических задач. Все стандартные функции математической библиотеки работают только с типом double. Рекомендуем вам никогда не использовать тип float!
Примеры описаний вещественных переменных:
double x, y, z; double a = 1.5, b = 1e+6, c = 1.5e-3;
В последних двух случаях использовалось задание вещественных констант в экспоненциальной форме (см. раздел 1.4.2).
Логический тип
В языке Си специального логического типа нет, вместо него используются переменные целого типа. Значению "истина" соответствует любое ненулевое целое число, значению "ложь" - ноль. Например, в Си допустим такой фрагмент программы:
int b; double s; . . . if (b) { s = 1.0; }
Здесь целочисленная переменная b используется в качестве условного выражения в операторе if ("если"). Если значение b отлично от нуля, то выполняется тело оператора if, т.е. переменной s присваивается значение 1.0 ; если значение b равно нулю, то тело оператора if не выполняется.
На самом деле, приведенный пример представляет собой дурной стиль программирования. Гораздо яснее выглядит следующий фрагмент, эквивалентный приведенному выше:
if (b != 0) { s = 1.0; }
В более строгом языке Java второй фрагмент корректен, а первый нет.
Язык C++ вводит логический тип bool в явном виде (отметим, что этот тип появился в C++ далеко не сразу!). Переменные типа bool принимают два значения: false и true (ложь и истина). Слова false и true являются ключевыми словами языка C++.
Примеры описания логических переменных в C++:
bool a, b; bool c = false, d = true;
Оператор sizeof
Переменная одного и того же типа на разных платформах может занимать различное число байтов памяти. Язык Си предоставляет программисту возможность получить размер элемента данного типа или размер переменной в байтах, для этого служит оператор sizeof. Аргумент sizeof указывается в круглых скобках, он может быть типом или переменной. Рассмотрим несколько примеров. Пусть определены следующие переменные:
int i; char c; short s; long l; double d; float f; bool b;
Тогда приведенные ниже выражения в 32-разрядной архитектуре имеют следующие значения:
размер переменной | размер типа | значение |
---|---|---|
sizeof(i) | sizeof(int) | 4 |
sizeof(c) | sizeof(char) | 1 |
sizeof(s) | sizeof(short) | 2 |
sizeof(l) | sizeof(long) | 4 |
sizeof(d) | sizeof(double) | 8 |
sizeof(f) | sizeof(float) | 4 |
sizeof(b) | sizeof(bool) | 1 |
Тип void
Слово void означает "пустота". Тип void в Си обозначает отсутствие чего-либо там, где обычно предполагается описание типа. Например, функция, не возвращающая никакого значения, в Си описывается как возвращающая значение типа void:
void f(int x);
Другое применение ключевого слова void состоит в описании указателя общего типа, когда заранее не известен тип объекта, на который он будет ссылаться.