Тип данных определяет
диапазон допустимых значений и соответственно - пространство, отводимое в памяти
данных, для переменных, констант и результатов, возвращаемых функциями. К стандартным типам данных языка C относятся: signed char; unsigned char; int; unsigned int; long; unsigned long; float; long long; unsigned
long long. В компиляторе WinAVR определены собственные целочисленные
типы (видимо для того, чтобы не возникло путаницы с другими компиляторами,
например с borland),
определённые в заголовочных файлах stdint.h и inttypes.h, если
подключается заголовочный файл inttypes.h, то
автоматически подключается и stdint.h.
В заголовочном файле stdlib.h определены
ещё два типа данных, используемых со
стандартными функциями div () и ldiv ().
Typedef |
Длина (биты | байты) |
Диапазон значений |
||||
signed
char |
8 | 1 |
0 ..
255 |
int8_t |
int_least8_t |
int_fast8_t |
|
char |
8 | 1 |
-128 ..
127 |
uint8_t |
uint_least8_t |
uint_fast8_t |
|
int |
16 | 2 |
0 ..
65 535 |
int16_t |
int_least16_t |
int_fast16_t |
intptr_t |
unsigned
int |
16 | 2 |
-3 2768
.. 32 767 |
uint16_t |
uint_least16_t |
uint_fast16_t |
uintptr_t |
long |
32 | 4 |
0 .. 4
294 967 295 |
int32_t |
int_least32_t |
int_fast32_t |
int_farptr_t |
unsigned
long |
32 | 4 |
-2 147 483 648 …2
147 483 647 |
uint32_t |
uint_least32_t |
uint_fast32_t |
uint_farptr_t |
float |
32 | 4 |
±1,175*10-38..
±3,402*1038 |
|
|
|
|
long long |
64 | 8 |
0 ..
1.844 E19 |
int64_t |
int_least64_t |
int_fast64_t |
intmax_t |
unsigned
long long |
64 | 8 |
-9.22E**18 …9.22 E18 |
uint64_t |
uint_least64_t |
uint_fast64_t |
uintmax_t |
double |
64 | 8 |
|
|
|
|
|
Пользовательские типы.
Кроме
того язык С позволяет объявлять собственные типы. Для этого используется
ключевое слово typedef, например:
typedef
unsigned char ut8_t; //объявляем тип ut8_t
typedef int t16_t; //объявляем тип ut16_t
Переменная —
это именованная величина определенного типа, которая может изменяться в ходе выполнения
программы. Для объявления переменных (т.е., выделения для них памяти) в
программе на C используется следующая конструкция:
тип_переменной идентификатор1, идентификатор2, . . .;
например:
int i; //Объявление
целочисленной переменной i
char cl, c2; //Объявление
символьных переменных cl и с2
Для
доступа к переменной в программе используется соответствующий идентификатор
(обязательно после объявления переменной). Значения, присваиваемые переменной,
должны соответствовать ей по типу (или правилам приведения типов,
рассматриваемым ниже).
Примеры:
i = 2; //Ошибка! Переменная
i еще не
объявлена
int i; //Объявление целочисленной
переменной i
float f; //Объявление
вещественной переменной f
i = 2; //Переменной i присвоено
значение 2
f = 3.3 //Переменной
f
присвоено значение 3,3
f = i; //Переменной
f
присвоено значение переменной
i
/*(в
данном случае будет
выполнено автоматическое приведение типов,
т.е. f = 2.0)*/
По
области видимости переменные могут быть глобальными и локальными. К глобальным
переменным имеют доступ все функции программы. Такие переменные
объявляются в программе перед объявлением всех функций. К локальным
переменным имеет доступ только та функция, в которой они объявлены.
Область видимости переменных.
Имена
переменных обладают определенной областью видимости, которая
подразумевает, что компилятор использует переменные в соответствии с тем, где
они находятся. Имена переменных, объявленных внутри функции, имеют область
видимости, ограниченную конкретной функцией. Например, в нескольких функциях
можно объявить переменную int i, которая в каждой функции не будет иметь никакой связи
с аналогичными переменными в других функциях. Точно так же и переменная,
объявленная внутри блока (ограниченного фигурными скобками {…}), остается
локальной по отношению к этому блоку.
Глобальные переменные имеют область
видимости, которая начинается от места их объявления и продолжается до конца
программного файла. Для того чтобы глобальную переменную можно было
использовать в других файлах, ее нужно объявить с помощью ключевого слова extern:
extern int n;
Объявленную таким образом
переменную, прежде, чем ее использовать, следует обязательно инициализировать
во внешнем файле некоторым значением.
ВНИМАНИЕ
Использование переменных,
объявленных с помощью, ключевого слова extern, часто приводит к ошибкам в программах,
поэтому применяйте их только тогда, когда нет другой альтернативы, и будьте при этом очень внимательны.
Константа — это
именованная величина определенного типа, которая, в отличие от переменной, не
может изменяться в ходе выполнения программы, а имеет конкретное значение, определенное
в момент объявления. Для объявления констант в программе на C используется следующая конструкция:
const тип
_константы идентификатор = значение;
Например:
const int i = 10;
//Объявление
целочисленной константы i.
Величина, объявленная как константа,
будет размещена компилятором AVR GCC в памяти RAM, то есть в той же области памяти, где хранятся переменные.
Для доступа к константе используется
ее идентификатор.
Примеры:
с =
'А'; //Ошибка! Константа
с еще не
объявлена
int i; //Объявление
целочисленной переменной i
const с =
'А'; //Объявление константы
с
i = 2;
//Переменной i присвоено
значение 2
с = i; //Ошибка! Попытка присвоить
значение константе
i = с; //Переменной i присвоено
значение константы с.
/* В данном
случае будет выполнено
автоматическое приведение
типов, т.е. i =
65 (ASCII-код символа 'А') */
Перечислимый тип — это
объявление списка целочисленных констант, которые можно явно не
инициализировать (в этом случае компилятор считает, что первая константа в
списке принимает значение 0, вторая — 1 и т.д.). Для подобного объявления
используется ключевое слово enum:
int n;
enum (zero, one, two); //zero = 0; one = 1; two = 2
n = one;
//n = 1
Если требуется изменить начальное значение
для списка констант, то можно указать его явно при объявлении, например:
enum
(three = 3,
four, five); //three
= 3; four
= 4; five
= 5
Приведение типов — это
принудительное преобразование значения одного типа к другому, совместимому с
исходным. Это важно при выполнении арифметических операций, когда полученные
значения могут выходить за допустимые пределы.
Приведение типов бывает явным и
неявным. Неявное приведение типов используется в операторах присваивания,
когда компилятор сам выполняет необходимые преобразования без участия
программиста.
Для явного приведения типа некоторой
переменной перед ней следует указать в круглых скобках имя нового типа,
например:
int X;
int Y = 200;
char С = 30;
X = (int) C * 10
+ Y; //Переменная С
приведена к типу int
Если бы в этом примере не было
выполнено явное приведение типов, то компилятор предположил бы, что выражение
С * 10 — это восьмиразрядное умножение (разрядности типа char) и вместо корректного значения 300 (0х12С) в
стек было бы помещено урезанное значение 44 (0х2С). Таким образом, в результате
вычисления выражения С * 10 + Y переменной X было бы присвоено значение 640, а не корректное
3200.
В результате приведения типа
переменная C распознается компилятором как
16-тиразрядная, и описанной выше ошибки не возникает.
Оператор sizeof. Оператор sizeof применяется
для вычисления размера области памяти (в байтах), отводимой под некоторую
переменную, результат выражения или тип. Например:
int а;
float f;
а = sizeof (int); //a = 2
а = sizeof (f); //a = 4
f = 3.3;
a = sizeof(f + a); //a = 4, поскольку тип результата – float
Правила преобразований
из одной системы счисления в другую.
Для
перевода чисел из одного вида в другой можно использовать калькулятор Windows в инженерном виде.
Схема
преобразования из некоторой системы счисления в десятичную очень проста: каждый
разряд умножаем на основание системы, возведенное в соответствующую разряду
степень (начиная с 0), и затем складываем полученные произведения для всех
разрядов. Пример для десятичного числа 100:
0b01100100 =
0*27+1*26+1*25+0*24+0*23+1*22+0*21+0*2°
= 0+64+32+0+0+4+0+0 = 100;
0144 = 1*82 + 4*81 + 4*8° =
64 + 32 + 4 = 100;
0x64 = 6*161
+ 4*16° = 96 + 4 = 100.
Для
преобразования из десятичного представления в другую систему счисления число
следует разделить на основание системы, запомнить остаток, затем частное еще
раз разделить на основание системы, опять запомнить остаток и т.д. до тех пор,
пока не будет получено неделимое частное. Это частное является старшим
разрядом полученного представления, а остальные разряды формируются из
остатков, начиная от последнего к первому.
Пример
преобразования числа 100 в двоичную систему счисления:
100/2 = 50, остаток 0
50/2 = 25, остаток 0
25/2 = 12, остаток 1
12/2 = 6, остаток 0
6/2 = 3,
остаток 0
3/2 = 1, остаток 1
1 — на 2 не делится. Результат: 100 = 0b1100100.
Пример
преобразования числа 100 в восьмеричную систему счисления:
100/8
= 12, остаток 4
12/8 = 1, остаток 4
1 — на 8 не делится. Результат: 100 = 0144.
Пример
преобразования числа 100 в шестнадцатеричную систему счисления:
100/16 = 6,
остаток 4
6 — на 16 не делится. Результат: 100 = 0x64.