Понимание типов данных, приведения типов и структур в C

11

C строго контролирует то, что хранится в памяти. Он не догадывается. Вы должны точно указать, какие именно данные вы сохраняете. Это не просто придирчивость. Это влияет на то, как работает ваша программа, сколько памяти она использует и будут ли ваши вычисления корректными или бессмысленными.

Стандартные типы переменных

В C есть три стандартных типа переменных.

Целое число: int
Это 4-байтовое целое число. Оно работает с целыми числами.

Число с плавающей точкой: float
Это 4-байтовое число с плавающей точкой. Оно работает с десятичными дробями.

Символ: char
Это 1-байтовый одиночный символ. Например, «a» или «3». Строка в C — это просто массив таких символов.

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

  • double : 8-байтовое число с плавающей точкой. Более высокая точность.
  • short : 2-байтовое целое число. Меньше памяти, меньший диапазон значений.
  • unsigned short или unsigned int : Эти типы работают только с положительными целыми числами. Без бита знака. Если вам нужно отслеживать количество населения или размеры пакетов, это часто правильный выбор.

Операторы и приоритет операторов

Операторы в C выглядят привычно.

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

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

Посмотрите на этот код:

Он выводит значение с плавающей точкой, потому что a объявлен как тип float. Но значение a будет равно 3.0. Почему? Потому что код сначала выполнил целочисленное деление. 10, деленное на 3, равно 3. Результат равен 3. Затем это 3 преобразуется в 3.0 при сохранении в a. Точность была потеряна еще до того, как значение попало в переменную.

Приоритет операторов в C следует стандартным правилам. Умножение и деление выполняются перед сложением и вычитанием.

Результат выражения 5+3*4 равен 17. А не 32. Оператор * имеет более высокий приоритет, чем +. Вы можете переопределить это с помощью скобок. (5+3)*4 равно 32. Сначала вычисляется 5+3.

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

Приведение типов (Typecasting)

C позволяет преобразовывать типы на лету. Это часто делается с указателями. Также оно происходит автоматически при присваивании для определенных типов.

В приведенном выше примере целочисленный результат 10/3 был автоматически преобразован в float. Но что, если вам нужна дробная часть?

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

Замените a=10/3; на a=(float)10/3;.

Теперь a равно 3.33333. Число 10 преобразуется в число с плавающей точкой до деления. Деление происходит в контексте чисел с плавающей точкой. Результат сохраняет свои десятичные разряды.

typedef

Вы можете объявлять именованные типы, определяемые пользователем, в C с помощью оператора typedef. Это широко распространено в коде на C.

Это позволяет объявлять логические типы (Boolean). В старых стандартах C нет встроенного типа bool, поэтому это обходной путь.

Если вам не нравится слово «float», вы можете написать:

Затем позже:

Размещайте инструкции typedef в любом месте программы. Просто убедитесь, что они идут перед первым использованием.

Структуры

Структуры в C группируют переменные в один пакет.

Каждый раз, когда вы хотите объявить структуру типа rec, вы должны писать struct rec. Это легко забыть. Если вы опустите слово struct, компилятор выдаст ошибки.

Вы можете сократить код:

Здесь объявление типа и переменная r объявляются в одном операторе.

Или используйте typedef для имени структуры. Если вам надоело каждый раз писать struct rec r :

Затем объявляйте записи, указывая:

Обращайтесь к полям с помощью точки. r.a = 5;.

Массивы

Массивы объявляются путем указания размера после обычного объявления.

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

Инкремент и декремент

В C есть сокращения для распространенных операций.

  • i = i + 1; становится i++;
  • i = i - 1; становится i--;
  • i = i + 3; становится i += 3;
  • i = i * j; становится i *= j;

Это не просто синтаксический сахар. Они часто компилируются в более эффективный машинный код. Используйте их.

Ошибки в C, которых следует избегать

Оператор / с двумя целыми числами — это ловушка. Он отбрасывает десятичную часть. Всегда проверяйте свои типы перед делением. Если вам нужна точность, сначала приведите один из операндов к float или double.

Думайте об этом каждый раз, когда используете этот оператор. В противном случае ваши числа будут неверными. А отладка проблем, связанных с целочисленным делением, — это мучительно.

Попробуйте сами

  • Экспериментируйте с приведением типов. Попробуйте int, char, float. Посмотрите, что происходит, когда вы смешиваете их.
  • Создайте массив записей. Напишите код для сортировки этого массива по одному целочисленному полю. Это научит вас работать с указателями, компоновкой памяти и управлением потоком выполнения.

Детали имеют значение в C. Пропустите один тип, и вся программа сломается. Сделаете все правильно, и она будет работать быстро.