Типы данных в языке Си : целые, вещественные, символьные

Типы данных в языке Си

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

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

  • Статическая типизация — контроль типов осуществляется при компиляции.
  • Динамическая типизация — контроль типов осуществляется во время выполнения.

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

Различают простые, составные и прочие типы данных.

Простые данные

Простые данные можно разделить на
  • целочисленные
  • вещественные
  • символьные
  • логические

Составные (сложные) данные

  • Массив — индексированный набор элементов одного типа.
  • Строковый тип — массив, хранящий строку символов.
  • Структура — набор различных элементов (полей записи), хранимый как единое целое и предусматривающий доступ к отдельным полям структуры.

Другие типы данных

  • Указатель — хранит адрес в памяти компьютера, указывающий на какую-либо информацию, как правило — указатель на переменную.

Программа, написанная на языке Си, оперирует с данными различных типов. Все данные имеют имя и тип. Обращение к данным в программе осуществляется по их именам (идентификаторам).

Идентификатор — это последовательность, содержащая не более 32 символов, среди которых могут быть любые буквы латинского алфавита a — z, A — Z, цифры 0 — 9 и знак подчеркивания (_). Первый символ идентификатора не должен быть цифрой.

Несмотря на то, что допускается имя, имеющее до 32 символов, определяющее значение имеют только первые 8 символов. Помимо имени, все данные имеют тип. Указание типа необходимо для того, чтобы было известно, сколько места в оперативной памяти будет занимать данный объект.

Компилятор языка Си придерживается строгого соответствия прописных и строчных букв в именах идентификаторов и лексем.

Верно Неверно
int a = 2, b;
b = a+3;
Int a=2;  // правильно int
INT a=2;
int a = 2, b; b = A + 3; // идентификатор А не объявлен

Пример объявления объектов

 
 
int n;    // Переменная n целого типа
double a; // Переменная a вещественного типа двойной точности

Целочисленные данные

Целочисленные данные могут быть представлены в знаковой и беззнаковой форме.

Беззнаковые целые числа представляются в виде последовательности битов в диапазоне от 0 до 2n-1, где n-количество занимаемых битов.

Знаковые целые числа представляются в диапазоне -2n-1…+2n-1-1. При этом старший бит данного отводится под знак числа (0 соответствует положительному числу, 1 – отрицательному).

Основные типы и размеры целочисленных данных:

Количество бит Беззнаковый тип Знаковый тип
8 unsigned char 0…255 char -128…127
16 unsigned short 0…65535 short -32768…32767
32 unsigned int int
64 unsigned long int long int

Вещественные данные

Вещественный тип предназначен для представления действительных чисел. Вещественные числа представляются в разрядной сетке машины в нормированной форме.

Нормированная форма числа предполагает наличие одной значащей цифры (не 0) до разделения целой и дробной части. Такое представление умножается на основание системы счисления в соответствующей степени. Например, число 12345,678 в нормированной форме можно представить как

12345,678 = 1,2345678·104

Число 0,009876 в нормированной форме можно представить как

0,009876 = 9,876·10-3

В двоичной системе счисления значащий разряд, стоящий перед разделителем целой и дробной части, может быть равен  только 1. В случае если число нельзя представить в нормированной форме (например, число 0), значащий разряд перед разделителем целой и дробной части равен 0.

Значащие разряды числа, стоящие в нормированной форме после разделителя целой и дробной части, называются мантиссой числа.

В общем случае вещественное число в разрядной сетке вычислительной машины можно представить в виде 4 полей.

Поля вещественного типа данных
  • знак — бит, определяющий знак вещественного числа (0 для положительных чисел, 1 — для отрицательных).
  • степень — определяет степень 2, на которую требуется умножить число в нормированной форме. Поскольку степень 2 для числа в нормированной форме может быть как положительной, так и отрицательной, нулевой степени 2 в представлении вещественного числа соответствует величина сдвига, которая определяется как

    2n-1,

    где n — количество разрядов, отводимых для представления степени числа.
  • целое — бит, который для нормированных чисел всегда равен 1, поэтому в некоторых представлениях типов этот бит опущен и принимается равным 1.
  • мантисса — значащие разряды представления числа, стоящие после разделителя целой и дробной части в нормированной форме.

Различают три основных типа представления вещественных чисел в языке Си:

Тип Обозначение в Си Кол-во бит Биты степени Мантисса Сдвиг
простое float 32 30…23 22…0 127
двойной точности double 64 62…52 51…0 1023
двойной расширенной точности long double 80 78…64 62…0 16383

Как видно из таблицы, бит целое у типов float и double отсутствует. При этом диапазон представления вещественного числа состоит из двух диапазонов, расположенных симметрично относительно нуля. Например, диапазон представления чисел типа float можно представить в виде:

Диапазон представления данных типа float

Пример: представить число -178,125 в 32-разрядной сетке (тип float).

Для представления числа в двоичной системе счисления преобразуем отдельно целую и дробную части:

17810 = 101100102.

0,12510 = 0,0012.

Тогда

178,12510 = 10110010,0012=1,0110010001·2111

Для преобразования в нормированную форму осуществляется сдвиг на 7 разрядов влево).

Для определения степени числа применяем сдвиг:

0111111+00000111 = 10000110.

Таким образом, число -178,125 представится в разрядной сетке как

-178,25 в разрядной сетке

Символьный тип

Символьный тип хранит код символа и используется для отображения символов в различных кодировках. Символьные данные задаются в кодах и по сути представляют собой целочисленные значения. Для хранения кодов символов в языке Си используется тип char.

Подробнее о кодировке символов.

Логический тип

Логический тип применяется в логических операциях, используется при алгоритмических проверках условий и в циклах и имеет два значения:

  • истина — true
  • ложь — false

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

21 комментарий к “Типы данных в языке Си”

  1. Михаил

    Здравствуйте форумчане !
    Не могу найти объяснения в простейшей программке:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {     //float a,b,e,f;
         double a,b,e,f;
          b=0;        //Начало счёта
          e=10 ;     //// КОНЕЦ СЧЁТА
          f=0.05;     /*  Приращение */
          for (a=b;a<=e;a=a+f)
         {
           printf("%.3f\t",a);
         }
        printf("\n");
        printf("Last A= %.18f\n",a);
        printf("     F=   %.18f     0x%x\n\n",f,f);// Вот он "ПОЛТЕРГЕЙСТ" !!!
        printf("Prob 1-2 Poltergeist\n");
        return 0;
    }

    Переменная F больше на 0.(17 нулей)3 чем заданное значение f=0.05, т.е на самом деле f=0,050000000000000003. И эти 0.(17 нулей)3 в цикле не дают "досчитать" до 10.
    Если переменные заявить как float, то картина будет ещё веселее.
    Если кто знает как с этим бороться, поясните плиз. Объявление переменных long double не работает- возвращаются нули.

    1. Елена

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

    1. Елена Вставская

      Для этого лучше воспользоваться бытовыми полями в языке Си. Но данные будут сохраняться всё равно кратно байтам.
      Интересна цель для 5-битных данных. Где они будут использоваться?

  2. Александр

    Здравствуйте)
    Задана переменная w типа беззнаковый символ и равная 241. Какое значение примет она после выполнения операции: w&=0xC7;
    Вот код:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
    using namespace std;

    void main()
    {
      unsigned char w = 241;
      w &= 0xC7;
      cout << w << endl;

    }

    При компиляции в visual 17 выводится непонятный символ и всё. Подскажите пожалуйста, в чём ошибка?

    1. Елена Вставская

      Поскольку код переменной больше 127, это вторая половина ASCII-таблицы. А кодовая страница в windows и в консоли не совпадает. Поэтому и символ в консоли может отличаться от ожидаемого.
      Посмотрите тему "создание консольного приложения" на сайте.

    1. Елена Вставская

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

  3. Здравствуйте! Не могли бы вы подсказать где здесь ошибка:

    1
    2
    3
    double k=1.00;
    int i=2, q=3;
    k +=(double)(i/q);

    k дает результат 0. Уверенна, что ошибка в типах, но не могу найти.

    1. Елена Вставская

      Ошибка в порядке действий

      1
      k +=((double)i)/q;

      В Вашем случае сначала целое 2 делится на 3. Получается 0. А затем этот 0 приводится к типу double.
      Я сначала привожу 2 к типу double, а потом делю уже вещественное число.

  4. Григорий

    Всем доброго время суток! Я совсем начинающий , поэтому не посылайте сразу. Подскажите как в while(1){} переменной присвоить(определить) тип данных? Именно в цикле.

    Пример:(естественно компилятор ругается)

    1
    2
    3
    4
    5
    6
    7
    8
    while (1) 
        {
        if(~PINB&(1<<0))
        {
          _delay_ms(200),(unsigned char x ++);// ???
          ICR1= uint16_t(f_pwm-=200);//???
          
        }
    1. Елена Вставская

      Не понятно, что за переменная x и зачем она нужна? В ней и проблема. Что предполагалось сделать в этой строчке?

      1. Григорий

        Елена, спасибо что ответили!!! Я учусь программировать микроконтроллеры.
        Я написал кусок кода где инкрементирую нажатие кнопки (x). Я читаю статьи из нета, где-то попадался код в котором автор в цикле определяет тип данных. На тот момент мне без надобности а сейчас уже и не найду где видел. Не только в х проблема, еще компилятор ругается на

        1
        ICR1= uint16_t(f_pwm-=200);

        f_pwm тоже переменная. Было-бы красиво определить их в цикле а не в шапке проекта.
        В связи с выше изложенным — Вопрос не отпал.

        1. Елена Вставская

          Надеюсь, что регистр ICR1 16- битный? В этом случае корректнее записать так:

          1
          2
          f_pwm-=200;
          ICR1=(uint16_t)f_pem;
          1. Григорий

            Спасибо!!! Я все понял, не нужно в одной строке стока заданий путать.
            ICR1= uint16_t(f_pwm-=200). Нужно как Вы написали. Спасибо. Буду к Вам обращаться.

  5. Алексей

    Объясните пожалуйста что значит фраза "определяющее значение имеют только первые 8 символов". Спасибо.

    1. Елена Вставская

      Различие в именах переменных должно содержаться в первых 8 символах.

  6. Николай

    В абзаце:

    "Для определения степени числа применяем сдвиг:
    0111111+00000111 = 10000110."

    видимо есть ошибка вместо 0111111, должно быть число 1111111, если я всё правильно понял.

    1. Елена Вставская

      Нет, ошибки нет. В качестве сдвига берется число, у которого старший разряд равен 0, а все остальные равны 1 (середина диапазона). И к этому числу добавляется положительная или отрицательная степень представляемого в разрядной сетке числа.

      1. Александра

        Для определения степени числа применяем сдвиг:

        0111111+00000111 = 10000110.
        А что эта степень тогда значит? И почему мы ее именно так получаем?

        1. Елена Вставская

          Степень числа может быть как положительной, так и отрицательной. Нулевой степени соответствует величина сдвига. Если нормированное число должно быть умножено на 2 в нулевой степени, то в биты степени записывается 011…1.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх