Арифметические типы
(См. также тип — обзор системы типов и список утилит, связанных с типами, предоставляемых библиотекой C.)
Логический тип
Обратите внимание, что преобразование к _Bool(до C23)bool(начиная с C23) работает не так, как преобразование к другим целочисленным типам: | (начиная с 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)
| (начиная с C99) |
| (начиная с 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).
| (начиная с 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 Существуют три комплексных типа:
Примечание: как и для всех спецификаторов типов, допускается любой порядок: 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
Каждый комплексный тип имеет такое же представление объекта и требования к выравниванию, как и массив из двух элементов соответствующего вещественного типа (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 Комплексные числа можно использовать с арифметическими операторами Инкремент и декремент для комплексных типов не определены. Операторы сравнения для комплексных типов не определены (понятие «меньше» отсутствует). Между комплексными типами и другими арифметическими типами определены неявные преобразования. Чтобы поддержать модель одной бесконечности в арифметике комплексных чисел, C считает любое комплексное значение, у которого хотя бы одна часть бесконечна, бесконечностью, даже если другая часть является NaN, гарантирует, что все операторы и функции соблюдают основные свойства бесконечностей, и предоставляет #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. Существуют три мнимых типа:
Примечание: как и для всех спецификаторов типов, допускается любой порядок: 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
Каждый из трёх мнимых типов имеет такое же представление объекта и требование к выравниванию, как и его соответствующий вещественный тип (float для float imaginary, double для double imaginary, long double для long double imaginary). Примечание: несмотря на это, мнимые типы являются отдельными и несовместимы со своими соответствующими вещественными типами, что запрещает алиасинг. Мнимые числа можно использовать с арифметическими операторами Инкремент и декремент для мнимых типов не определены. Между мнимыми типами и другими арифметическими типами определены неявные преобразования. Мнимые числа позволяют естественным образом представлять все комплексные числа в виде Мнимые типы также упрощают реализацию: умножение мнимого числа на комплексное можно непосредственно реализовать двумя умножениями при поддержке мнимых типов, вместо четырёх умножений и двух сложений. | (начиная с 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 |
|
|
| 64 | IEEE-754 |
|
|
|
| 80[примечание 1] | x86 |
|
|
|
| 128 | IEEE-754 |
|
|
|
| десятичная плавающая точка | 32 | IEEE-754 |
|
|
| 64 | IEEE-754 |
|
||
| 128 | IEEE-754 |
|
||
- Представление объекта обычно занимает 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