Spec-Zone.ru › C

Арифметические типы

(См. также тип для обзора системы типов и список утилит, связанных с типами, предоставляемых библиотекой C.)

Тип Boolean

  • _Bool (также доступен как макрос bool)(до C23)bool(с C23) - тип, способный хранить одно из двух значений: 1 и ​0​ (также доступны как макросы true и false)(до C23)true и false(с C23).

Обратите внимание, что преобразование в _Bool(до C23)bool(с C23) работает не так, как преобразование в другие целочисленные типы: (bool)0.5 оценивается как true, тогда как (int)0.5 оценивается как ​0​.

(с C99)

Типы символов

  • signed char - тип для представления символов со знаком.
  • unsigned char - тип для представления символов без знака. Также используется для проверки представлений объектов (сырой памяти).
  • char - тип для представления символов. Эквивалентен либо signed char или unsigned char (который определяется реализацией и может контролироваться параметрами компилятора), но char является отдельным типом, отличным от signed char и unsigned char.

Обратите внимание, что стандартная библиотека также определяет псевдонимы wchar_t , char16_t и char32_t(с C11) для представления широких символов и char8_t для символов UTF-8(с C23).

Целочисленные типы

  • short int (также доступен как short, может использовать ключевое слово signed)
  • unsigned short int (также доступен как unsigned short)
  • int (также доступен как signed int)
  • unsigned int (также доступен как unsigned), беззнаковый аналог int, реализующий арифметику по модулю. Подходит для манипуляций с битами.
  • long int (также доступен как long)
  • unsigned long int (также доступен как unsigned long)
Это наиболее оптимальный целочисленный тип для платформы и гарантированно имеет размер не менее 16 бит. Большинство современных систем используют 32 бита (см. Модели данных ниже).
  • long long int (также доступен как long long)
  • unsigned long long int (также доступен как unsigned long long)
(с C99)
  • _BitInt(n) (также доступен как signed _BitInt(n)), целочисленные типы со знаком с точной шириной (где n заменяется целым выражением, определяющим точную ширину (включая бит знака), которая не может быть больше BITINT_MAXWIDTH из <limits.h>)
  • unsigned _BitInt(n), целочисленные типы без знака с точной шириной (где n заменяется целым выражением, определяющим точную ширину, которая не может быть больше BITINT_MAXWIDTH из <limits.h>)
(с C23)

Примечание: как и со всеми спецификаторами типов, порядок не имеет значения: unsigned long long int и long int unsigned long обозначают один и тот же тип.

Следующая таблица суммирует все доступные целочисленные типы и их свойства:

Спецификатор типа Эквивалентный тип Ширина в битах по модели данных
Стандарт C LP32 ILP32 LLP64 LP64
char
char не менее
8
8 8 8 8
signed char
signed char
unsigned char
unsigned char
short
short int не менее
16
16 16 16 16
short int
signed short
signed short int
unsigned short
unsigned short int
unsigned short int
int
int не менее
16
16 32 32 32
signed
signed int
unsigned
unsigned int
unsigned int
long
long int не менее
32
32 32 32 64
long int
signed long
signed long int
unsigned long
unsigned long int
unsigned long int
long long
long long int
(C99)
не менее
64
64 64 64 64
long long int
signed long long
signed long long int
unsigned long long
unsigned long long int
(C99)
unsigned long long int

Помимо минимального количества бит, стандарт C гарантирует, что 1 == sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long).

Примечание: это позволяет крайний случай, в котором байт имеет размер 64 бита, все типы (включая char) имеют ширину 64 бита, и sizeof возвращает 1 для каждого типа.

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

Модели данных

Выбранные каждой реализацией размеры основных типов вместе образуют модель данных. Широкое распространение получили четыре модели данных:

Системы с 32-битными процессорами:

  • LP32 или 2/4/4 (int 16-битный, long и указатель 32-битные)
    • Win16 API
  • ILP32 или 4/4/4 (int, long и указатель 32-битные);
    • Win32 API
    • Системы Unix и Unix-подобные (Linux, Mac OS X)

Системы с 64-битными процессорами:

  • LLP64 или 4/4/8 (int и long 32-битные, указатель 64-битный)
    • Win64 API
  • LP64 или 4/8/8 (int 32-битный, long и указатель 64-битные)
    • Системы Unix и Unix-подобные (Linux, Mac OS X)

Другие модели встречаются очень редко. Например, ILP64 (8/8/8: int, long и указатель 64-битные) встречался только в некоторых ранних 64-битных системах Unix (например, Unicos на Cray).

Обратите внимание, что типы целых чисел с точной шириной доступны в <stdint.h> начиная с C99.

Типы вещественных чисел с плавающей запятой

В C существует три или шесть(с C23) типа для представления вещественных значений с плавающей запятой:

  • float - тип с плавающей точкой одинарной точности. Соответствует формату IEEE-754 binary32, если поддерживается.
  • double - тип с плавающей точкой двойной точности. Соответствует формату IEEE-754 binary64, если поддерживается.
  • long double - тип с плавающей точкой расширенной точности. Соответствует формату IEEE-754 binary128, если поддерживается; в противном случае соответствует формату IEEE-754 binary64-extended, если поддерживается; в противном случае соответствует какому-либо формату расширенной плавающей точки, не соответствующему IEEE-754, при условии, что его точность выше, чем у binary64, а диапазон не хуже, чем у binary64; в противном случае соответствует формату IEEE-754 binary64.
    • Формат binary128 используется в некоторых реализациях HP-UX, SPARC, MIPS, ARM64 и z/OS.
    • Наиболее известный формат IEEE-754 binary64-extended — это 80-битный формат расширенной точности x87. Он используется во многих реализациях x86 и x86-64 (заметным исключением является MSVC, который реализует long double в том же формате, что и double, т.е. binary64).
Если реализация предварительно определяет макроконстанту __STDC_IEC_60559_DFP__, также поддерживаются следующие типы десятичных чисел с плавающей точкой.
  • _Decimal32 - Представляет формат IEEE-754 decimal32.
  • _Decimal64 - Представляет формат IEEE-754 decimal64.
  • _Decimal128 - Представляет формат IEEE-754 decimal128.
В противном случае эти типы десятичных чисел с плавающей точкой не поддерживаются.
(с C23)

Типы с плавающей точкой могут поддерживать особые значения:

  • бесконечность (положительная и отрицательная), см. INFINITY
  • отрицательный ноль, -0.0. Он сравнивается как равный положительному нулю, но имеет значение в некоторых арифметических операциях, например, 1.0/0.0 == INFINITY, но 1.0/-0.0 == -INFINITY)
  • не число (NaN), которое не сравнивается как равное чему-либо (включая себя). Несколько битовых шаблонов представляют NaN, см. nan, NAN. Обратите внимание, что C не обращает особого внимания на сигнализирующие NaN (определенные в IEEE-754) и рассматривает все NaN как тихие.

Действительные числа с плавающей точкой могут использоваться с арифметическими операторами + - / * и различными математическими функциями из <math.h>. Как встроенные операторы, так и функции библиотеки могут вызывать исключения с плавающей точкой и устанавливать errno, как описано в math_errhandling.

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

Выражения с плавающей точкой также могут быть сжатыми, то есть вычисляться так, как будто все промежуточные значения имеют бесконечный диапазон и точность, см. #pragma STDC FP_CONTRACT.

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

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

См. Пределы типов с плавающей точкой и <math.h> библиотеку для дополнительной информации, пределов и свойств типов с плавающей точкой.

END_OF_DOCUMENT_MARKER

Комплексные типы с плавающей точкой

Комплексные типы с плавающей точкой моделируют математические комплексные числа, то есть числа, которые можно представить как сумму действительного числа и действительного числа, умноженного на мнимую единицу: a + bi

Три комплексных типа:

  • float _Complex (также доступен как float complex при включении <complex.h>)
  • double _Complex (также доступен как double complex при включении <complex.h>)
  • long double _Complex (также доступен как long double complex при включении <complex.h>)

Примечание: как и со всеми спецификаторами типов, любой порядок допустим: long double complex, complex long double, и даже double complex long обозначают один и тот же тип.

#include <complex.h>
#include <stdio.h>
 
int main(void)
{
    double complex z = 1 + 2*I;
    z = 1 / z;
    printf("1/(1.0+2.0i) = %.1f%+.1fi\n", creal(z), cimag(z));
}

Вывод:

1/(1.0+2.0i) = 0.2-0.4i

Если константа макроса __STDC_NO_COMPLEX__ определена реализацией, комплексные типы (а также заголовочный файл библиотеки <complex.h>) не предоставляются.

(с C11)

Каждый комплексный тип имеет такое же представление объекта и требования к выравниванию, как и массив из двух элементов соответствующего типа с плавающей точкой (float для float complex, double для double complex, long double для long double complex). Первый элемент массива содержит действительную часть, а второй – мнимую.

float a[4] = {1, 2, 3, 4};
float complex z1, z2;
memcpy(&z1, a, sizeof z1); // z1 becomes 1.0 + 2.0i
memcpy(&z2, a+2, sizeof z2); // z2 becomes 3.0 + 4.0i

Комплексные числа могут использоваться с арифметическими операторами + - * и /, возможно, совместно с мнимыми и действительными числами. В <complex.h> определено множество математических функций для комплексных чисел. Как встроенные операторы, так и функции библиотеки могут вызывать исключения с плавающей точкой и устанавливать errno, как описано в math_errhandling.

Инкремент и декремент не определены для комплексных типов.

Операторы сравнения не определены для комплексных типов (нет понятия «меньше»). Неявные преобразования определены между комплексными типами и другими арифметическими типами.

Для поддержки модели с одной бесконечностью для комплексной арифметики C рассматривает любое комплексное значение с хотя бы одной бесконечной частью как бесконечность, даже если другая часть – NaN, гарантирует, что все операторы и функции соблюдают базовые свойства бесконечностей и предоставляет cproj для отображения всех бесконечностей на каноническую бесконечность (см. арифметические операторы для точных правил).

#include <complex.h>
#include <math.h>
#include <stdio.h>
 
int main(void)
{
    double complex z = (1 + 0*I) * (INFINITY + I*INFINITY);
//  textbook formula would give
//  (1+i0)(∞+i∞) ⇒ (1×∞ – 0×∞) + i(0×∞+1×∞) ⇒ NaN + I*NaN
//  but C gives a complex infinity
    printf("%f%+f*i\n", creal(z), cimag(z));
 
//  textbook formula would give
//  cexp(∞+iNaN) ⇒ exp(∞)×(cis(NaN)) ⇒ NaN + I*NaN
//  but C gives  ±∞+i*nan
    double complex y = cexp(INFINITY + I*NAN);
    printf("%f%+f*i\n", creal(y), cimag(y));
}

Возможный вывод:

inf+inf*i 
inf+nan*i

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

умножение мнимой единицы на действительную бесконечность даёт корректно знаковое мнимое бесконечность: i × ∞ = i∞. Также, i × (∞ – i∞) = ∞ + i∞ указывает разумный квадрант.

Мнимые типы с плавающей точкой

Мнимые типы с плавающей точкой моделируют математические мнимые числа, то есть числа, которые можно записать как действительное число, умноженное на мнимую единицу: bi. Три мнимых типа:

  • float _Imaginary (также доступен как float imaginary при включении <complex.h>)
  • double _Imaginary (также доступен как double imaginary при включении <complex.h>)
  • long double _Imaginary (также доступен как long double imaginary при включении <complex.h>)

Примечание: как и со всеми спецификаторами типов, любой порядок допустим: long double imaginary, imaginary long double, и даже double imaginary long обозначают один и тот же тип.

#include <complex.h>
#include <stdio.h>
 
int main(void)
{
    double imaginary z = 3*I;
    z = 1 / z;
    printf("1/(3.0i) = %+.1fi\n", cimag(z));
}

Вывод:

1/(3.0i) = -0.3i

Реализация, которая определяет __STDC_IEC_559_COMPLEX__ рекомендуется, но не требуется для поддержки мнимых чисел. POSIX рекомендует проверить, определён ли макрос _Imaginary_I для определения поддержки мнимых чисел.

(до C11)

Мнимые числа поддерживаются, если __STDC_IEC_559_COMPLEX__(до C23)__STDC_IEC_60559_COMPLEX__(с C23) определён.

(с C11)

Каждый из трёх мнимых типов имеет такое же представление объекта и требование к выравниванию, как и соответствующий тип с плавающей точкой (float для float imaginary, double для double imaginary, long double для long double imaginary).

Примечание: несмотря на это, мнимые типы различны и не совместимы со своими соответствующими типами с плавающей точкой, что запрещает алиасинг.

Мнимые числа могут использоваться с арифметическими операторами + - * и /, возможно, совместно с комплексными и действительными числами. В <complex.h> определено множество математических функций для мнимых чисел. Как встроенные операторы, так и функции библиотеки могут вызывать исключения с плавающей точкой и устанавливать errno, как описано в math_errhandling.

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

Мнимые числа позволяют выразить все комплексные числа с помощью естественной нотации x + I*y (где I определяется как _Imaginary_I). Без мнимых типов определённые специальные комплексные значения нельзя создать естественным образом. Например, если I определяется как _Complex_I, то запись 0.0 + I*INFINITY даёт NaN в качестве действительной части, и нужно использовать CMPLX(0.0, INFINITY). То же самое относится к числам с отрицательной нулевой мнимой компонентой, которые имеют смысл при работе с функциями библиотеки с разрезами ветвей, такими как csqrt: 1.0 - 0.0*I приводит к положительной нулевой мнимой компоненте, если I определяется как _Complex_I, а отрицательная нулевая мнимая часть требует использования CMPLX или conj.

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

(с C99)

Ключевые слова

  • bool, true, false, char, int, short, long, signed, unsigned, float, double.
  • _Bool, _BitInt, _Complex, _Imaginary, _Decimal32, _Decimal64, _Decimal128.

Диапазон значений

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

До C23 Стандарт C допускал любое представление целых чисел со знаком, а минимальный гарантированный диапазон целых чисел со знаком N-бит был от \(\scriptsize -(2^{N-1}-1)\)-(2N-1-1) до \(\scriptsize +2^{N-1}-1\)+2N-1-1 (например, -127 до 127 для целого 8-битного типа со знаком), что соответствует пределам дополнительного кода или метода со знаком и величиной.

Однако, все популярные модели данных (включая все ILP32, LP32, LP64, LLP64) и почти все компиляторы C используют представление в дополнительном коде (единственные известные исключения — некоторые компиляторы для UNISYS), и начиная с C23, это единственное разрешенное стандартом представление с гарантированным диапазоном от \(\scriptsize -2^{N-1}\)-2N-1 до \(\scriptsize +2^{N-1}-1\)+2N-1-1 (например, −128 до 127 для знакового 8-битного типа).

Тип Размер в битах Формат Диапазон значений
Приблизительно Точно
character 8 знаковый −128 до 127
беззнаковый 0 до 255
16 UTF-16 0 до 65535
32 UTF-32 0 до 1114111 (0x10ffff)
integer 16 знаковый ± 3,27 · 104 −32768 до 32767
беззнаковый 0 до 6,55 · 104 0 до 65535
32 знаковый ± 2,14 · 109 −2 147 483 648 до 2 147 483 647
беззнаковый 0 до 4,29 · 109 0 до 4 294 967 295
64 знаковый ± 9,22 · 1018 −9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
беззнаковый 0 до 1,84 · 1019 0 до 18 446 744 073 709 551 615
двоично-плавающая точка 32 IEEE-754
  • мин. поднормализованное:
    ± 1,401,298,4 · 10−45
  • мин. нормализованное:
    ± 1,175,494,3 · 10−38
  • макс.:
    ± 3,402,823,4 · 1038
  • мин. поднормализованное:
    ±0x1p−149
  • мин. нормализованное:
    ±0x1p−126
  • макс.:
    ±0x1.fffffep+127
64 IEEE-754
  • мин. поднормализованное:
    ± 4,940,656,458,412 · 10−324
  • мин. нормализованное:
    ± 2,225,073,858,507,201,4 · 10−308
  • макс.:
    ± 1,797,693,134,862,315,7 · 10308
  • мин. поднормализованное:
    ±0x1p−1074
  • мин. нормализованное:
    ±0x1p−1022
  • макс.:
    ±0x1.fffffffffffffp+1023
80[примечание 1] x86
  • мин. поднормализованное:
    ± 3,645,199,531,882,474,602,528
    · 10−4951
  • мин. нормализованное:
    ± 3,362,103,143,112,093,506,263
    · 10−4932
  • макс.:
    ± 1,189,731,495,357,231,765,021
    · 104932
  • мин. поднормализованное:
    ±0x1p−16445
  • мин. нормализованное:
    ±0x1p−16382
  • макс.:
    ±0x1.fffffffffffffffep+16383
128 IEEE-754
  • мин. поднормализованное:
    ± 6,475,175,119,438,025,110,924,
    438,958,227,646,552,5 · 10−4966
  • мин. нормализованное:
    ± 3,362,103,143,112,093,506,262,
    677,817,321,752,602,6 · 10−4932
  • макс.:
    ± 1,189,731,495,357,231,765,085,
    759,326,628,007,016,2 · 104932
  • мин. поднормализованное:
    ±0x1p−16494
  • мин. нормализованное:
    ±0x1p−16382
  • макс.:
    ±0x1.ffffffffffffffffffffffffffff
    p+16383
десятичная
плавающая точка
32 IEEE-754
  • мин. поднормализованное:
    ± 1 · 10-101
  • мин. нормализованное:
    ± 1 · 10-95
  • макс.:
    ± 9,999'999 · 1096
64 IEEE-754
  • мин. поднормализованное:
    ± 1 · 10-398
  • мин. нормализованное:
    ± 1 · 10-383
  • макс.:
    ± 9,999'999'999'999'999 · 10384
128 IEEE-754
  • мин. поднормализованное:
    ± 1 · 10-6176
  • мин. нормализованное:
    ± 1 · 10-6143
  • макс.:
    ± 9,999'999'999'999'999'999'
    999'999'999'999'999 · 106144
  1. Представление объекта обычно занимает 96/128 бит на 32/64-битных платформах соответственно.

Примечание: фактические (в отличие от гарантированных минимальных) диапазоны доступны в заголовках библиотеки <limits.h> и <float.h>.

См. также

Документация C++ для Базовые типы

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/arithmetic_types

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API