算术类型
(可参阅类型,以获得类型系统综述,及 C 库提供的类型相关工具列表)
布尔类型注意,到 _Bool 的转换与到其他整数类型的转换不同: (bool)0.5 求值为 1 ,然而 (int)0.5 求值为 0 。 |
(C99 起) |
字符类型
- signed char - 用作有符号字符表示的类型。
- unsigned char - 用作无符号字符表示的类型。亦可用于查看对象表示(无修饰内存)。
- char - 用于字符表示的类型。 与 signed char 或 unsigned char 等价(具体等价于哪个是实现定义的,并且可以通过编译器命令行开关控制),但 char 是独立的类型,与 signed char 及 unsigned char 都不相同。
注意:标准亦定义了 typedef 名 wchar_t 、 char16_t 及 char32_t (C11 起) 以表示宽字符。
整数类型
- 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 )
|
(C99 起) |
注意:同所有类型说明符,允许任意顺序: unsigned long long int 和 long int unsigned long 指名同一类型。
下表总结所有可用的整数类型及其属性:
类型说明符 | 等价类型 | 数据模型中的位宽 | ||||
---|---|---|---|---|---|---|
C 标准 | LP32 | ILP32 | LLP64 | LP64 | ||
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 on Cray )。
注意从 C99 开始可从 <stdint.h> 中使用准确宽度的整数。
实浮点类型
C 拥有三或六 (C23 起)种表示实浮点值的类型:
- float - 单精度浮点类型。若支持则匹配 IEEE-754 binary32 格式。
- double - 双精度浮点类型。若支持则匹配 IEEE-754 binary64 格式。
- long double - 扩展精度浮点类型。若支持则匹配 IEEE-754 binary128 格式,否则若支持则匹配 IEEE-754 binary64 扩展格式,否则匹配某种精度优于 binary64 而值域至少和 binary64 一样好的非 IEEE-754 扩展浮点格式,否则匹配 IEEE-754 binary64 格式。
- 一些 HP-UX、 SPARC、 MIPS、 ARM64 和 z/OS 实现使用 binary128 格式。
- 最知名的 IEEE-754 binary64 扩展格式是 80 位 x87 扩展精度格式。许多 x86 和 x86-64 实现使用它(一个典型的例外是 MSVC ,它将 long double 实现为与 double 相同的格式,即 binary 64)。
|
(C23 起) |
浮点类型可以支持特殊值:
- 无穷大(正与负),见 INFINITY
- 负零,-0.0。它与正零比较相等,但对于某些算术运算有意义(例如 1.0/0.0 == INFINITY ,但 1.0/-0.0 == -INFINITY )。
- 非数( NaN ),它与任何值比较不相等(包括其自身)。有多种位模式表示 NaN ,见 nan 、 NAN 。注意 C 对( IEEE-754 所指定的) NaN 信号不作任何留意,并安静处理所有 NaN 。
实浮点数可用与算术运算符 + - / *和来自 math.h 的大量数学函数一同使用。内建运算符和库函数都可能引发浮点异常,并以 math_errhandling 中描述的方式设置 errno 。
浮点表达式可拥有大于其类型所指示的范围和精度,见 FLT_EVAL_METHOD 。赋值、 return 和转型强制将范围和精度变成声明类型所关联者。
浮点表达式亦可被缩略,即仿佛中间值拥有无限范围和精度一般计算,见 #pragma STDC FP_CONTRACT。
一些浮点数上的运算会受到浮点环境的影响,或修改它(最值得注意的是舍入方向)
实浮点类型与整数、复数和虚数类型间的隐式转换有定义。
附加细节、极限和浮点类型属性见浮点类型极限与 math.h 库。
复浮点类型复浮点类型模仿数学的复数,即可以写成一个实数与一个实数乘虚数单位的和的数: a + bi 三种复数类型是
注意:同所有类型说明符,允许任意顺序: long double complex 、 complex long double ,甚至 double complex long 都指名同一类型。 运行此代码 输出: 1/(1.0+2.0i) = 0.2-0.4i
每个复数类型与拥有二个对应实数类型( float 之于 float complex ,double 之于 double complex , long double 之于 long double complex )元素的数组相同的对象表示和对齐要求。数组第一元素保有实部,而第二个元素保有虚部。 复数可用于算术运算符 + - * 和 / , complex.h 中为复数定义许多数学函数。内建运算符和库函数都可能引发浮点异常,并按 math_errhandling 中描述的方式设置 errno 。 复数类型中不定义自增和自减。 复数类型中不定义关系运算符(没有“小于”的记号)。
为支持复数算术的一个无限模型, C 认可任何至少有一个无限部分的复数值为无穷大,即使另一部分是 NaN ,保证所有运算符和函数忠实于无穷大的基本属性,并提供 cproj 以映射所有无穷大到标准的一(准确规则见算术运算符)。 运行此代码 #include <stdio.h> #include <complex.h> #include <math.h> int main(void) { double complex z = (1 + 0*I) * (INFINITY + I*INFINITY); // 教科书公式会给出 // (1+i0)(∞+i∞) ⇒ (1×∞ – 0×∞) + i(0×∞+1×∞) ⇒ NaN + I*NaN // 但 C 给出复无穷大 printf("%f + i*%f\n", creal(z), cimag(z)); // 教科书方程会给出 // cexp(∞+iNaN) ⇒ exp(∞)×(cis(NaN)) ⇒ NaN + I*NaN // 但 C 给出±∞+i*nan double complex y = cexp(INFINITY + I*NAN); printf("%f + i*%f\n", creal(y), cimag(y)); } 可能的输出: inf + i*inf inf + i*nan C 也会处理多重无穷大,以在可能的地方保留方向信息,不管笛卡尔表示的固有限制: 实无穷大乘虚数单位,会给出对应符号的虚无穷大: i × ∞ = i∞ 。同理, i × (∞ – i∞) = ∞ + i∞ 指示合理的象限。
虚浮点类型虚浮点类型模仿数学的虚数,即可以写成实数乘虚数单位的数: bi 三种虚数类型是
注意:同所有类型说明符,允许任意顺序: long double imaginary 、 imaginary long double ,甚至 double imaginary long 都指名同一类型。 运行此代码 输出: 1/(3.0i) = -0.3i
三种虚数类型各拥有与其对应实数类型( float 之于 float imaginary , double 之于 double imaginary , long double 之于 long double imaginary )相同的对象表示和对齐要求。 注意:尽管如此,虚数类型是独立的,且与其对应实数类型不兼容,这禁止别名使用。 虚数可用于 算术运算符 + - * 及 / ,并且可与复数和实数混用。 complex.h 中为虚数类型定义多个数学函数。内建运算符和库函数都可能引发浮点异常,并按描述于 math_errhandling 的方式设置 errno 。 自增和自减不定义于虚数类型。
虚数类型零通过自然记号 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 结果有正零的虚部,并要求用 CMPLX 或 conj 获得负零虚部。 虚数类型亦会简化实现:若支持虚数则复数乘虚数可以直接实现为二次乘法,而非四次乘法和二次加法。 |
(C99 起) |
关键词
char, int, short, long, signed, unsigned, float, double. _Bool, _Complex, _Imaginary, _Decimal32, _Decimal64, _Decimal128
取值范围
下表提供常用数值表示的界限的参考。
C23 之前,C 标准曾允许任意的有符号整数表示,而 N 位有符号整数的最小保证范围为从 -(2N-1
-1) 到 +2N-1
-1 (例如有符号 8 位类型为 -127 到 127 ),这对应于反码或原码的界限。
然而,所有通行数据模型(含 ILP32、 LP32、 LP64、 LLP64 全体)和几乎所有的 C 编译器(已知的仅有例外是 UNISYS 的一些编译器)均使用补码表示,而从 C23 起,这是标准所允许的唯一表示,所保证的范围为从 -2N-1
到 +2N-1
-1 (例如有符号 8 位类型为 -128 到 127 )。
类型 | 位数 | 格式 | 取值范围 | |
---|---|---|---|---|
近似 | 精确 | |||
字符 | 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 |
|
- ↑ 在 32/64 位平台上对象表示通常占用 96/128 位。
注意:实际(与保证最小值相对)的范围可在库头文件 <limits.h> 和 <float.h> 中获得