Skip to content

Ch 7: 基本类型详解

  • 掌握整数类型的细节(溢出、无符号)
  • 理解浮点数的精度问题
  • 学会字符和字符串的处理
  • 理解类型的大小和平台差异
# Python - True/False
is_valid = True
is_empty = False
# 布尔运算
if is_valid and not is_empty:
print("OK")
# 布尔值可以参与算术运算
result = True + True # 2
// C++ - true/false(小写)
bool is_valid = true;
bool is_empty = false;
// 布尔值输出
std::cout << std::boolalpha << is_valid; // 输出 "true"
std::cout << std::noboolalpha << is_valid; // 输出 "1"
// 布尔值转换
bool b1 = 42; // true(非零转为 true)
bool b2 = 0; // false(零转为 false)
bool b3 = "hello"; // 编译错误!字符串不能转 bool
// bool 的大小是 1 byte(不是 1 bit)
std::cout << sizeof(bool); // 1
// 但只能存储 true(1) 或 false(0)
bool flag = true;
flag = false;
// 布尔值可以参与算术运算(隐式转换)
bool a = true; // 1
bool b = false; // 0
int sum = a + b; // 1
// 算术值转布尔值
int x = 1;
bool flag2 = x; // true
// 逻辑运算符
bool a = true, b = false;
bool and_result = a && b; // false
bool or_result = a || b; // true
bool not_result = !a; // false
// 短路求值
if (ptr != nullptr && ptr->value > 0) {
// ptr != nullptr 为 false 时,不执行 ptr->value > 0
}
// 注意:运算符重载可能导致不短路
类型典型大小范围使用场景
int4 bytes-2³¹ ~ 2³¹-1默认整数
unsigned int4 bytes0 ~ 2³²-1位运算、计数
long4-8 bytes平台相关平台原生整数
long long8 bytes-2⁶³ ~ 2⁶³-1大整数
int8_t1 byte-128 ~ 127精确字节大小
int64_t8 bytes固定跨平台64位
# Python - 自动处理大整数(无溢出)
x = 2**62
x = x * 1000
print(x) # 正常计算,无溢出
// C++ - 溢出是未定义行为!
int i = 2'000'000'000;
i += i; // 溢出!int 无法表示 40 亿
// 结果:未定义(通常是负数)
// unsigned 溢出是定义行为(回绕)
unsigned int u = 4'000'000'000;
u += u; // u = 2'147'483'836(回绕到 0)
#include <cstdint>
#include <stdexcept>
// 安全的整数加法
int safe_add(int a, int b) {
if (a > 0 && b > INT_MAX - a) {
throw std::overflow_error("overflow");
}
return a + b;
}
// C++20 安全整数
// std::signed_arithmetic auto x = 42; // C++26
// 不要用无符号做循环计数
for (unsigned int i = 10; i >= 0; --i) { // 永远为 true!
// i 是 unsigned,不会小于 0
}
// 正确做法
for (int i = 10; i >= 0; --i) {
// 或者
for (unsigned int i = 10; i > 0; --i) {
// i-- 处理最后一次
}
类型大小精度Python 对应
float4 bytes~7 位十进制float
double8 bytes~15 位十进制float(默认)
long double16 bytes~34 位numpy.float128
// 声明和赋值
float f1 = 3.14f; // f/F 后缀
float f2{3.14f};
double d1 = 3.14; // 默认 double
long double ld = 3.14L; // L 后缀
// 科学计数法
double d2 = 1.23e-10; // 1.23 × 10⁻¹⁰
double d3 = 6.02e23; // 阿伏伽德罗常数
# Python - decimal 模块解决精度
from decimal import Decimal
result = Decimal("0.1") + Decimal("0.2") # Decimal('0.3')
// C++ - 浮点精度问题
#include <iomanip>
double a = 0.1;
double b = 0.2;
double sum = a + b;
std::cout << sum << std::endl; // 0.30000000000000004
std::cout << std::setprecision(20) << sum << std::endl; // 更精确显示
// 比较浮点数
if (std::abs(sum - 0.3) < 1e-9) { // epsilon 比较
std::cout << "约等于 0.3" << std::endl;
}
#include <cmath>
#include <limits>
// 无穷大
double inf = std::numeric_limits<double>::infinity();
// NaN (Not a Number)
double nan = std::nan(""); // Quiet NaN
// 检查
if (std::isnan(nan)) std::cout << "是 NaN" << std::endl;
if (std::isinf(inf)) std::cout << "是无穷" << std::endl;
// NaN 的诡异行为
double result = 0.0 / 0.0; // NaN
result = 1.0 / 0.0; // inf
-1.0 / 0.0; // -inf
// NaN 的传播特性
double a = std::nan("");
double b = a + 1; // 还是 NaN
// 不要用 == 比较浮点数
double a = 0.1 + 0.2;
double b = 0.3;
if (a == b) { // 永远不为 true!
// ...
}
// 正确做法
if (std::abs(a - b) < 1e-10) {
// 相等
}
// 或者用相对误差
bool nearly_equal(double a, double b, double rel_err = 1e-10) {
return std::abs(a - b) < rel_err * std::max(std::abs(a), std::abs(b));
}
// char - 单个字符(通常是 1 byte = 8 bits)
char c1 = 'A';
char c2 = 65; // ASCII 值
char c3 = '\x41'; // 十六进制
char c4 = '\n'; // 转义字符
// 注意:char 可以是有符号或无符号(实现定义)
char c5 = 255; // 可能是 -1
signed char sc = 255; // 明确有符号
unsigned char uc = 255; // 明确无符号
// 输出
std::cout << c1; // A
std::cout << (int)c1; // 65
ASCII字符说明
48-570-9数字
65-90A-Z大写字母
97-122a-z小写字母
// 判断字符类型
#include <cctype>
char c = 'A';
if (std::isalpha(c)) {} // 是否字母
if (std::isdigit(c)) {} // 是否数字
if (std::isalnum(c)) {} // 是否字母或数字
if (std::isspace(c)) {} // 是否空白字符
if (std::isupper(c)) {} // 是否大写
if (std::islower(c)) {} // 是否小写
char upper = std::toupper(c); // 'a' -> 'A'
char lower = std::tolower(c); // 'A' -> 'a'
转义含义ASCII
\n换行10
\tTab9
\r回车13
\\反斜杠92
\'单引号39
\"双引号34
\0空字符0
// char16_t - UTF-16
char16_t c16 = u'中'; // 中文字符
char16_t str16[] = u"你好"; // 字符串
// char32_t - UTF-32
char32_t c32 = U'中';
// wchar_t - 宽字符(系统相关)
wchar_t wc = L'中';
wchar_t wstr[] = L"你好";
#include <iostream>
int main() {
std::cout << "基本类型大小:" << std::endl;
std::cout << "sizeof(bool) = " << sizeof(bool) << std::endl;
std::cout << "sizeof(char) = " << sizeof(char) << std::endl;
std::cout << "sizeof(short) = " << sizeof(short) << std::endl;
std::cout << "sizeof(int) = " << sizeof(int) << std::endl;
std::cout << "sizeof(long) = " << sizeof(long) << std::endl;
std::cout << "sizeof(long long) = " << sizeof(long long) << std::endl;
std::cout << "sizeof(float) = " << sizeof(float) << std::endl;
std::cout << "sizeof(double) = " << sizeof(double) << std::endl;
std::cout << "sizeof(long double) = " << sizeof(long double) << std::endl;
// 指针大小(取决于架构)
std::cout << "sizeof(int*) = " << sizeof(int*) << std::endl;
std::cout << "sizeof(void*) = " << sizeof(void*) << std::endl;
return 0;
}
struct Heavy {
std::vector<int> v{1'000'000};
};
std::cout << sizeof(Heavy); // 24 bytes(只有指针),不计算 vector 内容!
42 // int
42u // unsigned int
42L // long
42LL // long long
42ul // unsigned long
42ull // unsigned long long
0xFF // 十六进制(255)
0b1010 // 二进制(10)C++14
010 // 八进制(8)
1'000'000 // C++14 数字分隔符
3.14 // double
3.14f // float
3.14L // long double
1e10 // 科学计数法
1e-5f // float 科学计数法
3.14e10L // long double 科学计数法
'A' // char
L'A' // wchar_t
u8'A' // char8_t (C++20)
u'A' // char16_t
U'A' // char32_t
"hello" // const char[6]
u8"hello" // const char8_t[6] (C++20)
u"hello" // const char16_t[6]
U"hello" // const char32_t[6]
L"hello" // const wchar_t[6]
R"(raw \n string)" // 原始字符串(不转义)
# Python - 自动类型提升
result = 3 + 3.14 # 3 转为 3.0,结果是 6.14
result = 3 / 2 # 浮点除,结果是 1.5
// C++ - 隐式转换规则
int i = 3;
double d = 3.14;
double result = i + d; // i 转 double: 6.14
// 整型提升
char c = 'A';
int ic = c; // char 转 int: 65
// 截断
double dx = 3.99;
int ix = dx; // 3,丢失小数部分
// static_cast - 编译期可检查的转换
double d = 3.14;
int i = static_cast<int>(d); // 3
// const_cast - 移除 const 属性
const int* pc = &i;
int* p = const_cast<int*>(pc); // 移除 const
// reinterpret_cast - 位层面重新解释
int* ip = &i;
char* cp = reinterpret_cast<char*>(ip); // 把 int* 当 char* 看
// dynamic_cast - 运行时多态转换
class Base { virtual void foo() {} };
class Derived : public Base {};
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b); // 安全检查
#include <limits>
#include <climits>
// 整数限制
std::cout << INT_MAX << std::endl; // 2147483647
std::cout << INT_MIN << std::endl; // -2147483648
std::cout << UINT_MAX << std::endl; // 4294967295
std::cout << LLONG_MAX << std::endl; // 9223372036854775807
// 浮点限制
std::cout << std::numeric_limits<double>::max() << std::endl;
std::cout << std::numeric_limits<double>::epsilon() << std::endl;
std::cout << std::numeric_limits<double>::infinity() << std::endl;
  • bool 是 1 byte,值只能是 true/false
  • 整数溢出是未定义行为(int),无符号是回绕行为
  • 浮点数有精度问题,用 epsilon 比较
  • char 是 1 byte,用单引号
  • 类型大小:sizeof(T) 返回字节数
  • 使用后缀指定字面量类型(u, L, f, LL)
  • 四种类型转换:static_cast、const_cast、reinterpret_cast、dynamic_cast

下章预告:ch08 学习字符串处理和 C++20 的 std::format 格式化。