Глава 2: Переменные и арифметика ================================== В этой главе мы изучим основные типы данных, как объявлять переменные, и выполним простые арифметические операции в языке C. Понимание этих основ критически важно, так как переменные являются строительными блоками для хранения и манипулирования данными в любой программе, а арифметика позволяет выполнять базовые вычисления. --- Типы данных ----------- Язык C предоставляет следующие базовые типы данных, каждый из которых предназначен для хранения определённого вида информации и занимает разный объём памяти: * ``int`` — **целое число**. Используется для хранения целых чисел без дробной части (например, 5, -100, 0). Размер ``int`` может варьироваться в зависимости от архитектуры системы (обычно 2 или 4 байта). * ``float`` — **число с плавающей точкой (одинарной точности)**. Предназначен для хранения дробных чисел (например, 3.14, -0.5, 123.456). Имеет меньшую точность по сравнению с ``double`` и обычно занимает 4 байта. * ``double`` — **число с плавающей точкой (двойной точности)**. Также используется для дробных чисел, но с гораздо большей точностью и диапазоном значений, чем ``float``. Обычно занимает 8 байт. Это тип по умолчанию для дробных чисел в C, если не указано иное. * ``char`` — **один символ**. Хранит один символ (например, 'A', 'z', '5', '!'). На самом деле, ``char`` хранит целочисленное значение, соответствующее коду символа в таблице ASCII (или другой кодировке). Обычно занимает 1 байт. * ``unsigned int``, ``long``, ``short`` и другие модификаторы. Это модификаторы, которые уточняют размер и диапазон значений базовых типов: * **``short``**: Уменьшает диапазон значений для ``int``, занимая меньше памяти (обычно 2 байта). Например, ``short int``. * **``long``**: Увеличивает диапазон значений для ``int`` и ``double``. Например, ``long int`` (обычно 4 или 8 байт) и ``long double`` (обычно 10 или 16 байт). * **``unsigned``**: Применяется к целочисленным типам (``int``, ``char``, ``short``, ``long``) и означает, что переменная может хранить только неотрицательные значения (но при этом её максимальное положительное значение удваивается). Например, ``unsigned int``. ### Важность выбора типа данных Выбор правильного типа данных важен по двум причинам: 1. **Эффективность использования памяти**: Использование меньших типов данных, когда это уместно, может сэкономить память, что особенно важно в программах, работающих с большими объёмами данных или на встроенных системах с ограниченными ресурсами. 2. **Точность и диапазон значений**: Неправильный выбор может привести к потере точности (например, при использовании ``float`` вместо ``double`` для финансовых расчётов) или переполнению (когда значение выходит за пределы допустимого диапазона для данного типа). Пример объявления переменных: .. code-block:: c int a = 5; // Объявление целого числа 'a' и инициализация его значением 5 float b = 3.14; // Объявление числа с плавающей точкой 'b' и инициализация 3.14 char c = 'A'; // Объявление символьной переменной 'c' и инициализация символом 'A' double d = 123.456789; // Объявление числа двойной точности 'd' unsigned int count = 100; // Объявление беззнакового целого числа 'count' --- Арифметические операции ----------------------- Язык C поддерживает стандартные арифметические операторы: +---------------+-----------------------+------------------------------------------------------------------------+ | Оператор | Назначение | Пример и пояснение | +===============+=======================+========================================================================+ | ``+`` | сложение | ``5 + 3`` будет ``8`` | +---------------+-----------------------+------------------------------------------------------------------------+ | ``-`` | вычитание | ``10 - 4`` будет ``6`` | +---------------+-----------------------+------------------------------------------------------------------------+ | ``*`` | умножение | ``2 * 7`` будет ``14`` | +---------------+-----------------------+------------------------------------------------------------------------+ | ``/`` | деление | ``10 / 3`` → ``3`` (целочисленно) ``10.0 / 3.0`` → ``3.333...`` | +---------------+-----------------------+------------------------------------------------------------------------+ | ``%`` | остаток от деления | ``10 % 3`` → ``1`` (10 делим на 3, остаток 1) | +---------------+-----------------------+------------------------------------------------------------------------+ --- **Важно**: оператор ``%`` (модуль или остаток от деления) работает только с **целыми числами** (``int``, ``short``, ``long``, ``char`` и их ``unsigned`` версии). Попытка использовать его с ``float`` или ``double`` приведёт к ошибке компиляции. ### Приоритет операций Как и в обычной математике, в C существует порядок выполнения арифметических операций: 1. Умножение (``*``), деление (``/``), остаток от деления (``%``). 2. Сложение (``+``), вычитание (``-``). Операции с одинаковым приоритетом выполняются слева направо. Для изменения порядка выполнения можно использовать **круглые скобки ``()``**. Пример: ``int result = 5 + 3 * 2;`` // ``result`` будет 11 (3 * 2 = 6, затем 5 + 6 = 11) ``int result_2 = (5 + 3) * 2;`` // ``result_2`` будет 16 (5 + 3 = 8, затем 8 * 2 = 16) --- Пример программы ---------------- Создадим программу ``math_demo.c``, в которой объявим переменные, выполним операции и выведем результат на экран. Этот пример демонстрирует, как разные типы данных влияют на результат деления. .. code-block:: c #include // Подключаем стандартную библиотеку ввода/вывода, необходимую для printf int main() { // Главная функция, с которой начинается выполнение программы // Объявление и инициализация целочисленных переменных int a = 10, b = 3; // Объявление и инициализация переменных с плавающей точкой float x = 10.0, y = 3.0; // Выполнение и вывод результатов целочисленных операций printf("a + b = %d\n", a + b); // %d - спецификатор формата для вывода целых чисел printf("a - b = %d\n", a - b); printf("a * b = %d\n", a * b); printf("a / b = %d\n", a / b); // Целочисленное деление: 10 / 3 = 3 (дробная часть отбрасывается) printf("a %% b = %d\n", a % b); // %% используется для вывода символа % в printf // Выполнение и вывод результата деления с плавающей точкой printf("x / y = %.2f\n", x / y); // %.2f - спецификатор для float, выводит 2 знака после запятой return 0; // Возвращаем 0, сигнализируя об успешном завершении программы } --- Компиляция и запуск ------------------- После того как вы создали файл ``math_demo.c``, вам нужно его скомпилировать и запустить. 1. **Сохраните файл**: Убедитесь, что вы сохранили код в файл с именем ``math_demo.c``. 2. **Компиляция**: Откройте терминал или командную строку и перейдите в каталог, где сохранён файл. Затем выполните команду: .. code-block:: bash gcc math_demo.c -o math_demo * ``gcc``: это название компилятора (GNU C Compiler), который преобразует ваш исходный код на C в исполняемый файл. * ``math_demo.c``: это имя вашего исходного файла. * ``-o math_demo``: это опция, которая указывает компилятору создать выходной исполняемый файл с именем ``math_demo``. Без этой опции исполняемый файл по умолчанию будет называться ``a.out`` (на Linux/macOS) или ``a.exe`` (на Windows). 3. **Запуск**: После успешной компиляции вы можете запустить программу, выполнив: .. code-block:: bash ./math_demo * ``./``: указывает операционной системе искать исполняемый файл в текущем каталоге. Вывод будет таким: .. code-block:: none a + b = 13 a - b = 7 a * b = 30 a / b = 3 a % b = 1 x / y = 3.33 --- Заметки ------- * **При делении целых чисел (``int / int``), результат всегда является целым числом**. Дробная часть просто отбрасывается (происходит **усечение**, а не округление). Например, ``7 / 2`` даст ``3``, а не ``3.5``. * **Чтобы получить точный результат деления, используйте ``float`` или ``double``** для хотя бы одного из операндов. Если один из операндов является типом с плавающей точкой, C автоматически преобразует другой операнд к этому типу перед выполнением деления. Это называется **неявным приведением типов**. * Пример: ``(float)a / b`` или ``a / y``. В первом случае ``a`` временно преобразуется во ``float``. * **Переполнение (Overflow)**: Будьте внимательны к переполнению. Если результат арифметической операции превышает максимальное значение, которое может хранить данный тип данных, это приведёт к непредсказуемому или некорректному поведению. Например, сложение двух больших ``int`` может дать отрицательное число, если результат превышает ``INT_MAX``. ### Дополнительные комментарии * **Инициализация переменных**: Хорошей практикой является всегда инициализировать переменные при их объявлении, чтобы избежать неопределённых значений (так называемого "мусора" в памяти). Если вы не инициализируете переменную, она будет содержать случайное значение, которое было в этом участке памяти до того, как переменная была объявлена. * **Константы**: Для значений, которые не должны меняться в течение выполнения программы, можно использовать ключевое слово ``const``. Например: ``const float PI = 3.14159;``. * **Вывод форматированных данных (``printf``)**: Функция ``printf`` очень мощная. Спецификаторы формата (``%d``, ``%.2f``, ``%c``) указывают, как интерпретировать и выводить переменные. ``\n`` используется для перехода на новую строку.