C/C++基本类型表示范围

C/C++ 的数据类型表示范围取决于编译器和硬件平台 ,但标准规定了最小范围,实际范围可通过 limits.hfloat.h 获取。以下以最常见的 32/64 位系统(LP64/ILP32/LLP64) 为准,列出典型范围。

1. 整型(整数类型)

1.1 有符号整型

类型 位数 最小值 最大值
signed char 8 -128 127
short (或 short int) 16 -32,768 32,767
int 32 -2,147,483,648 2,147,483,647
long (Linux 64位: 64位; Windows 64位: 32位) 32/64 -2,147,483,648 / -9.22e18 2,147,483,647 / 9.22e18
long long 64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807

1.2 无符号整型

类型 位数 最小值 最大值
unsigned char 8 0 255
unsigned short 16 0 65,535
unsigned int 32 0 4,294,967,295
unsigned long 32/64 0 4.29e9 / 1.84e19
unsigned long long 64 0 18,446,744,073,709,551,615

⚠️ 注意char 是否有符号由实现定义(通常为 signed char,但有些 ARM 工具链默认为 unsigned char)。


2. 浮点类型(IEEE 754)

类型 位数 最小值(正) 最大值 精度(有效十进制位数)
float 32 ≈1.175 × 10⁻³⁸ ≈3.402 × 10³⁸ 6~7 位
double 64 ≈2.225 × 10⁻³⁰⁸ ≈1.798 × 10³⁰⁸ 15~16 位
long double 80 / 128 (x86扩展精度) ≈3.36 × 10⁻⁴⁹³² ≈1.18 × 10⁴⁹³² 18~19 位

特殊值float/double 还可表示正负无穷(±INF)、NaN(非数值)、零(有符号零 ±0.0)。

3. 布尔型与字符类型

类型 取值 说明
bool (C++ / C99) true (1) 或 false (0) 占 1 字节(典型)
char -128~127 或 0~255 用于存储 ASCII 或 UTF-8 字节
wchar_t 平台相关(16/32位) 用于宽字符

4. void 类型

  • void :没有值,不能表示范围。用于无返回值函数或通用指针 void*

5. 如何获取本机的精确范围?

IEEE 754 通过将 SME 编码到固定的二进制位域中来实现存储。

例如:E=127 → 实际指数 0,E=128 → 实际指数 1,E=126 → 实际指数 -1。

(2) 非规格化值(Denormalized / Subnormal)

E == 0 且 M ≠ 0 时:

(3) 零值

E == 0M == 0 时:

(4) 无穷大(Infinity)

E == 255M == 0 时:

(5) 非数值(NaN, Not a Number)

E == 255M ≠ 0 时:

3.2 双精度(64 位)

包含头文件 <limits.h> (整型)和 <float.h>(浮点型)。

  • 示例:

    cpp 复制代码
    #include <stdio.h>
    #include <limits.h>
    #include <float.h>
    
    int main() {
        printf("int max: %d\n", INT_MAX);
        printf("double min positive: %e\n", DBL_MIN);
        return 0;
    }

    也可用 C++ 的 <limits> 模板:

    cpp 复制代码
    std::numeric_limits<int>::max();

    6. 标准最低要求(ISO C/C++ 保证)

    类型 最小位数 最小值 最大值
    signed char 8 -127 127
    short 16 -32,767 32,767
    int 16 -32,767 32,767
    long 32 -2,147,483,647 2,147,483,647
    long long (C99/C++11) 64 -9.22e18 9.22e18

    注意:标准允许采用补码原码,现代平台全是补码。

    任意一个二进制浮点数 V 可表示为:

    V = (-1)ˢ × M × 2ᴱ

  • S:符号位(Sign),0 表示正数,1 表示负数。

  • M:尾数(Significand 或 Mantissa),是一个二进制小数,范围通常为 [1, 2) 或 [0, 1),取决于指数部分。

  • E:指数(Exponent),对尾数进行缩放,可以是正数或负数。

  • IEEE 754 定义了多种浮点格式,最常用的是:

    类型 总位数 符号位 指数位 尾数位 指数偏移(Bias)
    单精度(binary32) 32 1 8 23 127
    双精度(binary64) 64 1 11 52 1023
    半精度(binary16) 16 1 5 10 15
    四精度(binary128) 128 1 15 112 16383

    3.1 单精度(32 位)

    cpp 复制代码
    [31]    符号位 S
    [30:23] 指数位 E (8 位)
    [22:0]  尾数位 M (23 位)

    表示的值分为几种情况(根据指数 E 的值):

    (1) 规格化值(Normalized)

    0 < E < 255(即 E 不全为 0 也不全为 1)时:

  • 实际指数 = E - Bias,Bias = 127。

  • 尾数隐含整数部分为 1,即实际尾数 = 1.M(二进制)。

  • 因此值 = (−1)S×1.M(2)×2E−127(−1)S×1.M(2)​×2E−127。

  • 实际指数 = 1 - Bias = -126(固定)。

  • 尾数隐含整数部分为 0,即实际尾数 = 0.M。

  • 值 = (−1)S×0.M×2−126(−1)S×0.M×2−126。

  • 作用:表示非常接近零的数,实现渐进下溢(gradual underflow),避免突然下溢到零。

  • 表示 ±0(符号位决定正负零)。正零和负零在算术上通常视为相等。

  • 表示 ±∞(符号位决定)。用于溢出结果,如 1.0/0.0。

  • 表示未定义或无效的运算结果,如 0.0/0.0,∞ - ∞ 等。

  • 可分类为 SNaN (Signaling NaN,会触发异常)和 QNaN(Quiet NaN,不触发异常),通常由 M 的最高位区分。

cpp 复制代码
[63]    符号位 S
[62:52] 指数位 E (11 位)
[51:0]  尾数位 M (52 位)

Bias = 1023。

  • 规格化范围:E 从 1 到 2046,实际指数 = E - 1023。

  • 非规格化:E = 0,M ≠ 0,实际指数 = -1022。

  • 无穷大:E = 2047,M = 0。

  • NaN:E = 2047,M ≠ 0。


7. 常见陷阱

  • 隐式类型转换 :有符号与无符号混合计算时,有符号会被转为无符号,可能导致意外结果(如 -1 > 0U 为真)。

  • 溢出 :有符号溢出是未定义行为 ;无符号溢出是模 2^n 运算。

浮点数比较

不要直接使用 == 比较两个浮点数,因为累积误差会导致本来相等的值微量不同。应使用:

cpp 复制代码
fabs(a - b) < epsilon

整数转浮点的精度丢失

当整数超过 2²⁴(单精度)或 2⁵³(双精度)时,无法精确表示所有整数,会产生舍入。

例:16777217 在单精度中会变成 16777216。

运算顺序影响精度

例如 (a+b)+ca+(b+c) 可能因舍入顺序不同导致结果有微小差异。

非规格化数性能问题

有些 CPU 在处理非规格化数时速度较慢(甚至产生异常),可通过设置 FTZ(Flush To Zero)标志强制将非规格化数视为 0 来提高性能(通常在图形或音频处理中)。
*

例题

复制代码
  一个 32位无符号整数可以表示的最大值,最接近下列哪个选项?

  A. 4×10^9    [*]
  B. 4×10^10
  C. 2×10^9
  D. 2×10^10

解析 :两种思路,一是 记住32位无符号数的表示范围为0-4,294,967,295,约为4x10**^9;**

  • 二是使用更通用的方法。计算一个十进制位需要多少个二进制位,虽然10不能使用整个二进制位表示,但可以按下面的思路推导出来。

  • 一个4进制位,可以用2个二进制位表示,因为log2(4)=2

  • 一个8进制位,可以用3个二进制位表示,因为log2(8)=3

  • 一个16进制位,可以用4个二进制位表示,因为log2(16)=4

  • .....

  • 那么一个10进制位,可以用多个少个二进制位表示呢?同样,可以按上面的计算方法,log2(10)≈3.22.

  • 32位无符号数可以表示为4x2^30. 30/3.22≈9.316≈9(舍0.316),因此,如果答案在A/B之间,应该选择A。同样,也可以表示成2x2^31. 31/3.22≈9.627≈10(入0.373),如果答案在c/d之间,应该选择D。显然,前者舍0.316,后者入0.373,前者更接近真实值。

复制代码
  32 位 int 类型的存储范围是( )?

   A. -2147483647 ~ +2147483647
   B. -2147483647 ~ +2147483648
   C. -2147483648 ~ +2147483647
   D. -2147483648 ~ +2147483648

解析:整数分为无符号数和有符号数,无符号数的范围为0-(2^n-1);有符号的范围为-2^(n-1)-(2^(n-1)-1).最小的负数是-2^(n-1),二进制表示为1000.....0.

相关推荐
yijianace1 小时前
Python爬虫实战:BooksToScrape 多线程爬取与图片下载
开发语言·爬虫·python
凡人叶枫1 小时前
Effective C++ 条款15:在资源管理类中提供对原始资源的访问
linux·开发语言·c++·stm32·单片机
swordbob1 小时前
Spring Boot 2.0 改 CGLIB 后,接口实现是否有影响
java·开发语言·spring
郝学胜-神的一滴1 小时前
中级OpenGL教程 009:用环境光告别模型死黑
前端·c++·unity·godot·图形渲染·opengl·unreal
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第106题】【并发篇】第6题:synchronized 锁的锁对象可以是什么?
java·开发语言·面试
质造者1 小时前
Python 本地 RAG 实战 | Ollama+ChromaDB 实现 PDF 离线智能问答
开发语言·python·pdf·大模型·rag
slandarer1 小时前
MATLAB | 韦恩图的高阶版: UpSet图 更新升级啦!
开发语言·matlab
Leweslyh1 小时前
3GPP TS 28.312 意图驱动管理服务 — 极详细通俗解读
开发语言·php
swordbob2 小时前
Spring事务失效的场景
java·开发语言·spring