Spec-Zone.ru › C

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

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

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

  • _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)

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

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

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

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

  • shortint (также доступен как short, может использовать ключевое слово signed)
  • unsignedshortint (также доступен как unsignedshort)
  • int (также доступен как signedint)
  • unsignedint (также доступен как unsigned), беззнаковый аналог int, реализующий арифметику по модулю. Подходит для манипуляций с битами.
  • longint (также доступен как long)
  • unsignedlongint (также доступен как unsignedlong)
Это наиболее оптимальный для платформы целочисленный тип; его ширина гарантированно составляет не менее 16 бит. В большинстве современных систем используется 32-битная ширина (см. раздел «Модели данных» ниже).
  • longlongint (также доступен как longlong)
  • unsignedlonglongint (также доступен как unsignedlonglong)
(начиная с C99)
  • _BitInt(n) (также доступен как signed_BitInt(n)), целочисленные типы со знаковым значением и точной битовой шириной (вместо n указывается целочисленное константное выражение, задающее точную ширину, включая бит знака; она не может превышать BITINT_MAXWIDTH из <limits.h>)
  • unsigned_BitInt(n), целочисленные типы беззнакового значения и точной битовой шириной (вместо n указывается целочисленное константное выражение, задающее точную ширину; она не может превышать BITINT_MAXWIDTH из <limits.h>)
(начиная с C23)

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

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

Спецификатор типа Эквивалентный тип Ширина в битах для моделей данных
Стандарт C LP32 ILP32 LLP64 LP64
char char не менее
8
8 8 8 8
signedchar signedchar
unsignedchar unsignedchar
short shortint не менее
16
16 16 16 16
shortint
signedshort
signedshortint
unsignedshort unsignedshortint
unsignedshortint
int int не менее
16
16 32 32 32
signed
signedint
unsigned unsignedint
unsignedint
long longint не менее
32
32 32 32 64
longint
signedlong
signedlongint
unsignedlong unsignedlongint
unsignedlongint
longlong longlongint
(C99)
не менее
64
64 64 64 64
longlongint
signedlonglong
signedlonglongint
unsignedlonglong unsignedlonglongint
(C99)
unsignedlonglongint

Помимо минимального количества бит, стандарт 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 бита)
    • API Win16
  • ILP32 или 4/4/4 (int, long и указатель имеют ширину 32 бита);
    • API Win32
    • Unix и Unix-подобные системы (Linux, Mac OS X)

64-битные системы:

  • LLP64 или 4/4/8 (int и long имеют ширину 32 бита, указатель — 64 бита)
    • API Win64
  • 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 — формат x87 расширенной точности с шириной 80 бит. Он используется во многих реализациях 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>.

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

Комплексные типы с плавающей точкой моделируют математические комплексные числа, то есть числа, которые можно представить в виде суммы вещественного числа и вещественного числа, умноженного на мнимую единицу: 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-битного типа).

Тип Размер в битах Формат Диапазон значений
Приблизительный Точный
символ 8 знаковый −128 до 127
беззнаковый 0 до 255
16 UTF-16 0 до 65535
32 UTF-32 0 до 1114111 (0x10ffff)
целое число 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/c/language/arithmetic_types

Spec-Zone.ru

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