Продолжаем освоение языка C.
И теперь пришло время познакомиться с типами данных, а также способами их представления, одним из которых являются переменные. Также есть ещё константы, но с ними мы будем знакомиться немного позже.
С типами данных мы уже частично познакомились, когда выводили данные различного типа напрямую в консоль посредством функции printf, не задавая их заранее и никак не преобразовывая. Конечно же, можно делать и так, но какой прок от программы, которая просто выводит данные, никак их не обрабатывая и ничего с ними не делая, это не совсем хорошо. Ведь на то он и процессор, чтобы заниматься какой-то автообработкой, а наша программа должна как-то его на это натолкнуть.
В данном уроке мы также не будем данные никак обрабатывать и преобразовывать, но он станет ещё одной ступенькой к данной теме — различным арифметическим и логическим преобразованиям данных, так как без переменных в данном случае не обойтись. Вообще, конечно, можно и обойтись, работая непосредственно с памятью, но это было бы весьма неудобно и ни о какой наглядности и читабельности не было бы и речи.
Прежде чем приступить к переменным, мы познакомимся с типами данных, являющимися самой главной основой переменных, так как переменная всегда несёт в себе и представляет какой-то определённый тип.
Данные различного типа — это величины, которые располагаются в каком-то месте памяти и могут занимать в ней различное количество пространства.
Типы данных можно разделить условно на три группы:
- целые — данные целого типа,
- вещественные — данные, которые могут иметь дробную часть,
- символы — данные типа char, которые представляют собой какой-то символ и занимают в памяти всего один байт.
Рассмотрим первый тип. Данные целого типа могут быть различной величины, следовательно будут иметь разный возможный диапазон значений, а также занимать различное количество байт в памяти. Также данные этого типа могут быть знаковыми (возможно отрицательное значение) или беззнаковыми (не меньше нуля).
Рассмотрим, какие бывают данные целого типа (в принципе char тоже можно считать целым типом малой величины, так как зачастую его используют в этом качестве, когда хотят оперировать малыми значениями, чтобы сэкономить память, так как они занимают в ней всего один байт).
Данная таблица, думаю, всё это расскажет:
Тип | Количество бит | Допустимый диапазон |
char | 8 | -128 … 127 |
unsigned char | 8 | 0 … 255 |
short |
16 | -32 768 … 32767 |
unsigned short |
16 | 0 … 65535 |
int |
32 | -2 147 483 648 … 2 147 483 647 |
unsigned int |
32 | 0 … 4 294 967 295 |
long | 32 | -2 147 483 648 … 2 147 483 647 |
unsigned long | 32 | 0 … 4 294 967 295 |
long long |
64 |
-9 223 372 036 854 775 808 … 9 223 372 036 854 775 807 |
unsigned long long | 64 | 0 … 18 446 744 073 709 551 615 |
Аналогичным образом ведёт себя и вещественный тип. Только представители данного типа могут иметь ещё некоторые свойства. Кроме того, что они тоже занимают в памяти каждый определенное количество байт и имеют диапазоны, они могут быть представлены ещё в нормированной форме — в виде числа, умноженного на 10 в определённой степени. Также данный вид представления называют экспоненциальной записью числа.
Например, число 135.543 можно представить как 1,35543 . 102.
А, например, число 0.00001245 — как 1.245 . 10-5.
Первый множитель — это мантисса или значащее число, а степень десятки — это экспонент или показатель, но чаще всего употребляется слово порядок, так как степень у нас именно десяти.
В коде мы так написать не можем, в исходном коде первое число будет выглядеть как 1.35543E2, а второе 1.245E-5.
Мы не будем сейчас вдаваться в подробности, как именно хранится вещественное число в ячейке памяти. Вообще, тема интересная, но в принципе, сейчас она нам особой пользы не принесёт.
Также посмотрим таблицу диапазонов и размера занимаемой памяти определённых вещественных типов
Тип | Количество бит | Допустимый диапазон |
float | 32 | -2 147 483 648.0 … 2 147 483 647.0 |
double | 64 |
-9 223 372 036 854 775 808 .0 … 9 223 372 036 854 775 807.0 |
long double |
64 |
-9 223 372 036 854 775 808 .0 … 9 223 372 036 854 775 807.0 |
В некоторой документации пишут, что последний тип занимает 80 бит в памяти. Пока не знаю, где правда, возможно это зависит от операционных систем, либо от каких-то стандартов, либо от компилятора. С этим, думаю, разберёмся позже, когда будем писать исходные коды, отлаживать их и смотреть результаты в дизассемблированном виде.
Про символьный тип говорить особо нечего, так как он в группе только один. Занимает он один байт в памяти.
Ещё существует тип данных bool. Это целочисленный тип данных, так как диапазон допустимых значений — целые числа от 0 до 255. Данный тип используется как логический тип данных исключительно для хранения результатов логических выражений. У логического выражения может быть один из двух результатов — true или false. true — если логическое выражение истинно, false — если логическое выражение ложно. Данный тип может отсутствовать в некоторых компиляторах вообще, тогда мы используем вместо него char либо unsigned char.
Думаю, что для первоначального знакомства с типами данных пока нам достаточно. С остальными тонкостями будем разбираться в процессе дальнейшего изучения языка по мере поступления вопросов.
Теперь о переменных.
Переменные существуют для хранения значений и величин определённых типов данных в памяти.
Для того, чтобы к этим значениям было удобно обращаться, у переменной существует имя. Это наподобие как и у людей, когда они для идентификации друг друга обращаются также по именам.
Самое основное требование для объявления переменной: переменная должна быть объявлена раньше, чем она будет использоваться.
Самый простой способ объявления переменной в коде следующий:
char symbol1;
Сначала мы указываем тип данных, который будет в себе нести наша переменная, а далее мы указываем имя нашей переменной.
Имя переменной должно быть уникальным, то есть недопустимо объявлять две переменных с одним и тем же именем.
Имя переменной для удобства должно отражать суть и назначение нашей переменной, она должна показывать нам, для чего мы её используем, то есть имя должно быть говорящим. Конечно, это не обязательно и никакие стандарты этого не предусматривают и делать это мы должны только для своего удобства, чтобы наш код легче потом читался. Так как язык C — язык для программиста, а ассемблер — это язык для процессора.
Тем не менее существует и стандарт для имени переменной. Не всякие символы можно использовать в имени переменной. можно использовать буквы только латинского алфавита, как верхнего так и нижнего регистра, причём язык C является языком регистрозависимым и, например, переменные с именами Symbol1 и symbol1 — это будут разные переменные.
Также разрешается использовать арабские цифры в именах переменных (от 0 до 9), только с одним ограничением — имя переменной не должно начинаться с цифры, например имя переменной 4symbol использовать запрещено, а s4ymbol — разрешено.
В именах переменных запрещено использовать пробелы, поэтому, например, имя переменной first var запрещено. Но чтобы нам как-то можно было больше рассказать о назначении переменных и всё же использовать там несколько слов, то вместо пробелов разрешено использовать подчёркивания — '_'. Поэтому мы сможем нашу переменную назвать как first_var. Также со знака подчёркивания допустимо начинать имя переменной, но злоупотреблять этим нежелательно, так как во многих библиотеках, в т.ч. стандартных, переменные, имя которых начинается со знака подчёркивания, очень часто используется. Тем самым мы избежим повторения имён, которое недопустимо.
Запрещено также в качестве имён использовать ключевые слова — такие, к примеру, как if, else, int, float. Данные слова зарезервированы и не могут быть использованы.
Также не допускается использование в именах операторов (+, -, = и т.д.), кавычек, скобок и т.д.
Тем не менее, не смотря на все ограничения, переменные — это очень удобный и необходимый механизм для хранения и модификации различных значений и величин.
Несколько переменных мы можем объявить как в разных строках
char symbol1;
int cnt;
float adc_val;
так и в одной
char symbol1; int cnt; float adc_val;
Если переменные объявляются одного типа, то мы можем их объединить в одно объявление. В этом случае имена данных переменных между собой мы разделяем запятыми
char symbol1, symbol2, symbol3;
В случае всех вышеперечисленных операций под переменные, которые мы объявили резервируется место в памяти в таком размере, какой предусматривает тип переменной, которую мы объявляем. В этом случае содержимое резервируемых ячеек памяти как правило не изменяется и значение переменной приобретёт случайную величину. Некоторые компиляторы автоматически присваивают значение 0 объявляемым переменным.
Чтобы переменная приобрела определённое значение, её следует либо инициализировать, либо присвоить ей результат какой-то операции.
Так как с различными операциями мы будем знакомиться не в данном уроке, то познакомимся пока с первым типом придания определённого значения переменной — это её инициализация.
Инициализируются переменные различными способами.
Мы можем сначала наши переменные объявить, а затем инициализировать
char symbol1, symbol2, symbol3;
int cnt;
float adc_val;
symbol1 = 'c';
symbol2 = 'f';
symbol3= 'h';
cnt = 589;
adc_val = 124.54f;
Таким образом мы присвоили нашим переменным определённые значения. Теперь мы с нашими переменными в дальнейшем можем осуществлять какие-то действия — арифметические, логические, также использовать их в параметрах вызываемых функций, например, с помощью функции printf вывести их значения в консоль.
Также мы можем проделать инициализацию наших переменных сразу — на этапе объявления
char symbol1 = 'c', symbol2 = 'f', symbol3= 'h';
int cnt = 589;
float adc_val = 124.54f;
Оператор '=' (равно) — это оператор присвоения. Используется для присвоения переменной, имя которой находится слева от оператора, значения либо результата выражения, находящегося справа от оператора.
Существует ещё несколько операторов, с которыми мы будем знакомиться в следующих уроках.
В следующей части занятия мы напишем исходный код, в котором объявим, инициализируем и выведем в консоль переменные различного типа и проверим работу кода на практике.
Предыдущий урок Программирование на C Следующая часть
Смотреть ВИДЕОУРОК (нажмите на картинку)
Ошибка.
Поправьте:
Используется для присвоения переменной, имя которой находится СЛЕВА от оператора, значения либо результата выражения, находящегося справа от оператора.
Ага, спасибо, поправил!
Я с детства путаю лево и право. Сначала перепутал, написал наоборот, потом исправил только в одном месте.
Спасибо за внимательное чтения материала ресурса!
Количество байт занимаемых переменной в памяти можно определить с помощью sizeof().