2025-03-27 12:49:00

Урок 3. Типы данных.

Переменные.

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

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

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

Типы данных.

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

Название типа Размер памяти  Диапазон значений Псевдонимы

char

1 байт

1 символ

 

unsigned char

1 байт

от 0 до 255

 

signed char

1 байт

от -128 до 127

 

short

2 байта

от 32768 до 32767

short int

signed short

signed short int

unsigned short

2 байта

от 0 до 65535

unsigned short int

int

2 байта или 4 байта

от 32768 до 32767 (при 2 байтах) или

от 2 147 483 648 до 2 147 483 647 (при 4 байтах)

signed int

signed<

unsigned int

2 байта или 4 байта

от 0 до 65535 (для 2 байт)

либо

от 0 до 4 294 967 295 (для 4 байт)

unsigned

long

4 байта или 8 байт

от -2 147 483 648 до 2 147 483 647 (4 байта),

либо 

-9223372036854775807 до +9 223 372 036 854 775 807 (8 байт).

long int

signed long int

signed long

unsigned long

4 байта или 8 байт

от 0 до 4 294 967 295 (4 байта)

или

от 0 до 18 446 744 073 709 551 615 (8 байт)

unsigned long int

long long

8 байт

от -9223372036854775807 до +9223372036854775807

long long int

signed long long int

signed long long

unsigned long long

8 байт

от 0 до 18446744073709551615

unsigned long long int

float

4 байта

от +/- 3.4E-38 до 3.4E+38

 

double

8 байт

от +/- 1.7E-308 до 1.7E+308.

 

long double

10 байт (80 бит), 96 бит или 128 бит

от +/- 3.4E-4932 до 1.1E+4932

 

void

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

   

 

Примеры объявления переменных:

int main {

     int a;

     unsigned int a;

     float f;

     int su, prime = 7; five = 5;

     char c, c2 = 'A', m=10;

}

ВНИМАНИЕ !!! Если не задано начальное значение переменной, то в ней хранится "мусор", оставшийся от предыдущего использования ячеек памяти.

Суффиксы.

В языке Си любое десятичное число по умолчанию считается либо int/long либо int/long long int. Когда происходит присваивание числа переменной, тип которой отличается от этих типов происходит преобразование числа в тип указанный у переменной. Что бы избежать этого преобразования можно явно указать к какому типу принадлежит число. Для этого используются суффиксы.

Тип Суффикс

unsigned int   unsigned long int  и unsigned long long int

u или U

unsigned long int и unsigned long long int

ul или UL

long long int

ll или LL

unsigned long long int

ull или ULL

 

Пример объявления переменной с суффиксом:

unsigned number = 123456789u;

Спецификаторы классов памяти и квалификатор const.

  • const Значение не будет меняться после инициализации. Пример: const unsigned int a = 123; При попытке изменить переменную произойдет ошибка компиляции.
  • static Место под переменную будет выделено в статической памяти, поэтому доступ к ней возможен во время всего времени работы программы. Инициализация выполняется до начала выполнения программы.
  • extern Глобальная переменная объявляется и инициализируется в другом файле. Доступ к переменной возможен во время всего выполнения программы.

Оператор присваивания и побочный эффект.

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

prog (a,a=k*2);

Примеры побочных эффектов в выражениях:

int main(void)

{

  int a, b, x=5, y, z;

  a = 5; //положить целое число 5 в переменную a

  x = x + 20; // x=25 побочный эффект

  y = (x - 15) * (x + a); // y=300

  z = y = a+1; // y=6 z=6 побочный эффект

}

Арифметические операции над целочисленными значениями.

  • сложение "+"
  • вычитание "–"
  • умножение "*"
  • деление нацело "/"
  • остаток от деления нацело "%"

При делении нацело результат всегда округляется в сторону нуля и выполняется равенство (a/b)*b + a%b = a, поэтому знак остатка совпадает со знаком делимого.

Явное приведение типов.

Для явного приведения типов имя типа указывается в круглых скобках перед переменной или выражением:

int X;

int Y = 200;

char C = 255;

X = (unsigned char)C * 10 + Y; 

Чтобы избежать неоднозначностей, рекомендуется явно указывать знаковость для типа char -1 или 255 иначе переменная С приводится к типу int.

Неявное приведение типов.

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

  • Если один из типов операндов – вещественный, то второй операнд тоже приводится к вещественному типу.
  • Если есть операнд целого типа короче, чем int и все значения этого типа могут быть представлены как int, то он преобразуется к int; иначе - к unsigned int.
  • Для операндов целых типов неявное приведение типов управляется целочисленным рангом приведения типа.

Примеры правила 1:

float f;

f = 3/2; //целочисленное деление f=1.0

f = 3./2; //вещественное деление f=1.5

int a = 7;

float x;

x = a / 4; // 1

x = 4 / a; // 0

x = (float)a / 4; // 1.75

x = 1.*a / 4; // 1.75

Примеры правила 2:

short  i, x=5,y=-2;

i = x + y;

переменные x и y сначала расширяются до типа int, выполняется сложение, а затем результат помещается в i

Примеры правила 3:

unsigned int u = 50;

int i = -500;

int answer = i / u; // answer = 85899335.

i будет приведен к беззнаковому типу и его значение будет равно 232-500 вместо -500, а результат деления будет приведен обратно к знаковому типу int

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

Унарные операции также являются операциями с побочным эффектом.

  • Инкремент “++” - увеличение операнда на единицу
  • Декремент “--” - уменьшение операнда на единицу

Есть две формы унарных операций - постфиксная и префиксная. В первом случае сначала происходит присваивание значения а потом унарная операция, во втором случае сначала инкремент или декремент, а потом присваивание:

Постфиксная форма

int a, b=7;

a =  b++;  // a=7 b=8 

Префиксная форма

int a, b=7;

a =  ++b;  // a=8 b=8

Точка следования.

Точкой следования (sequence point), называется место в программе, в котором все побочные эффекты предыдущих вычислений закончены, а новые – не начаты. Точками следования в программе являются:

  • конец полного выражения
  • при выполнении операции x , y – между вычислением x и y;
  • при выполнении операции z ? x : y – между вычислением z и вычислением x либо y; (рассмотрим это позднее)
  • при вызове функции – перед выполнением ее тела и после вычисления ее аргументов;
  • при выполнении операций x && y и x || y – между вычислением x и вычислением y.

Пример точки следования:

int a, b, c;

a = (a + b) * (c + 3); // после вычисления всего выражения.

Антипример:

int a, b = 10, c;

a = b++ + ++b; // ТАК НЕЛЬЗЯ !!! Дважды модифицируется одна переменная !!!

a = (c = 3) + (c = 3); // ТАК НЕЛЬЗЯ !!! Дважды модифицируется одна переменная !!!

 

 

 

Комментарии ()