命名空间
变体
操作

算术类型

来自 cppreference.cn
< c‎ | language

(另请参见类型获取类型系统概述,以及C标准库提供的与类型相关的实用程序列表。)

目录

布尔类型

  • _Bool(也可通过宏bool访问)(直至 C23)bool(自 C23 起) — 一种类型,能够持有以下两个值之一:10(也可通过宏truefalse访问)(直至 C23)truefalse(自 C23 起)

请注意,转换_Bool(直至 C23)bool(自 C23 起)与转换为其他整数类型的方式不同:(bool)0.5求值为true,而(int)0.5求值为0

(C99 起)

[编辑] 字符类型

  • signed char — 用于有符号字符表示的类型。
  • unsigned char — 用于无符号字符表示的类型。也用于检查对象表示(原始内存)。
  • char — 用于字符表示的类型。等同于signed charunsigned char(具体是哪一个由实现定义,并可能由编译器命令行开关控制),但char是一个不同的类型,与signed charunsigned char都不同。

请注意,标准库还定义了typedef名称wchar_tchar16_tchar32_t(自 C11 起)来表示宽字符以及char8_t表示UTF-8字符(自 C23 起)

[编辑] 整数类型

  • short int (也可访问为short, 可使用关键词signed)
  • unsigned short int (也可访问为unsigned short)
  • int (也可访问为signed int)
这是平台上最优的整数类型,并保证至少为16位。大多数当前系统使用32位(见下文数据模型)。
  • unsigned int (也可访问为unsigned),是int的无符号对应类型,实现模算术。适用于位操作。
  • long int (也可访问为long)
  • unsigned long int (也可访问为unsigned long)
  • long long int (也可访问为long long)
  • unsigned long long int (也可访问为unsigned long long)
(C99 起)
  • _BitInt(n)(也可访问为signed _BitInt(n)),位精确有符号整数类型(其中`n`被替换为一个整数常量表达式,表示精确宽度(包括符号位),不能大于<limits.h>中的BITINT_MAXWIDTH
  • unsigned _BitInt(n),位精确无符号整数类型(其中`n`被替换为一个整数常量表达式,表示精确宽度,不能大于<limits.h>中的BITINT_MAXWIDTH
(自 C23 起)

注意:与所有类型说明符一样,任何顺序都是允许的:unsigned long long intlong 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位系统

  • LP322/4/4 (int 为 16 位,long 和指针为 32 位)
  • Win16 API
  • ILP324/4/4 (intlong 和指针为 32 位);
  • Win32 API
  • Unix 和类 Unix 系统 (Linux, Mac OS X)

64 位系统

  • LLP644/4/8 (intlong 为 32 位,指针为 64 位)
  • Win64 API
  • LP644/8/8 (int 为 32 位,long 和指针为 64 位)
  • Unix 和类 Unix 系统 (Linux, Mac OS X)

其他模型非常罕见。例如,ILP648/8/8intlong和指针均为64位)仅出现在一些早期64位Unix系统(例如Cray上的Unicos)中。

请注意,自 C99 起,<stdint.h> 中提供了精确宽度的整数类型。

[编辑] 实浮点类型

C有三个或六个(自 C23 起)类型用于表示实浮点值

  • float — 单精度浮点类型。如果支持,匹配IEEE-754 binary32 格式
  • double — 双精度浮点类型。如果支持,匹配IEEE-754 binary64 格式
  • long double — 扩展精度浮点类型。如果支持,匹配IEEE-754 binary128 格式;否则,如果支持,匹配IEEE-754 binary64 扩展格式;否则,匹配某些非IEEE-754 扩展浮点格式,只要其精度优于binary64且范围至少与binary64相同;否则,匹配IEEE-754 binary64 格式。
    • 某些HP-UX、SPARC、MIPS、ARM64和z/OS实现使用binary128格式。
    • 最著名的IEEE-754 binary64扩展格式是80位x87扩展精度格式。它被许多x86和x86-64实现使用(一个显著的例外是MSVC,它以与double相同的格式(即binary64)实现long double)。
如果实现预定义了宏常量 __STDC_IEC_60559_DFP__,则还支持以下十进制浮点类型。
否则,不支持这些十进制浮点类型。
(自 C23 起)

浮点类型可能支持特殊值

  • 无穷大(正和负),参见INFINITY
  • 负零-0.0。它与正零比较相等,但在某些算术运算中具有意义,例如1.0 / 0.0 == INFINITY,但1.0 / -0.0 == -INFINITY
  • 非数值 (NaN),它不与任何值(包括自身)比较相等。多个位模式表示NaN,参见nanNAN。请注意,C不特别关注信令NaN(由IEEE-754指定),并将所有NaN视为安静NaN。

实浮点数可与算术运算符+ - / *以及<math.h>中的各种数学函数一起使用。内置运算符和库函数都可能引发浮点异常并设置errno,如math_errhandling所述。

浮点表达式可能具有比其类型指示的更大的范围和精度,请参见FLT_EVAL_METHOD赋值返回强制转换会强制范围和精度与声明的类型关联。

浮点表达式也可以被“收缩”(contracted),即,计算时假设所有中间值都具有无限范围和精度,参见#pragma STDC FP_CONTRACT

对浮点数的一些操作会受浮点环境状态的影响并修改其状态(最显著的是舍入方向)。

实浮点类型与整数、复数和虚数类型之间定义了隐式转换

有关浮点类型的更多详细信息、限制和属性,请参阅浮点类型的限制<math.h>库。

复浮点类型

复浮点类型模拟数学上的复数,即可以写成实数和乘以虚数单位的实数之和的数:a + bi

这三种复数类型是

注意:与所有类型说明符一样,任何顺序都是允许的:long double complexcomplex 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 complexdouble 对应于 double complexlong 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这三种虚数类型是

注意:与所有类型说明符一样,任何顺序都是允许的:long double imaginaryimaginary 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 imaginarydouble 对应 double imaginarylong 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)时是有意义的:如果I定义为_Complex_I,则1.0 - 0.0*I会产生正零虚部,而负零虚部需要使用CMPLXconj

虚数类型还简化了实现;如果支持虚数类型,虚数与复数的乘法可以直观地通过两次乘法实现,而不是四次乘法和两次加法。

(C99 起)

[编辑] 关键词

[编辑] 值范围

下表提供了常见数值表示的限制参考。

在C23之前,C标准允许任何有符号整数表示,并且N位有符号整数的最小保证范围是从-(2N-1
-1)
+2N-1
-1
(例如,8位有符号类型为-127127),这对应于反码符号和幅度的限制。

然而,所有流行的数据模型(包括所有ILP32、LP32、LP64、LLP64)和几乎所有C编译器都使用二进制补码表示(唯一已知的例外是一些UNISYS编译器),并且自C23起,它是标准允许的唯一表示,保证范围从-2N-1
+2N-1
-1
(例如,8位有符号类型为-128127)。

类型 位大小 格式 值范围
大约 精确
字符 8 signed −128127
unsigned 0255
16 UTF-16 065535
32 UTF-32 01114111 (0x10ffff)
整数 16 signed ± 3.27 · 104 −3276832767
unsigned 06.55 · 104 065535
32 signed ± 2.14 · 109 −2,147,483,6482,147,483,647
unsigned 04.29 · 109 04,294,967,295
64 signed ± 9.22 · 1018 −9,223,372,036,854,775,8089,223,372,036,854,775,807
unsigned 01.84 · 1019 018,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. 对象表示通常在32/64位平台上分别占用96/128位。

注意:实际(而非保证最小)范围可在库头文件<limits.h><float.h>中获得。

[编辑] 参见

C++ 文档,关于基本类型