一、基本定义
类型 | 全称/含义 | 本质 | 常见别名 |
---|---|---|---|
int | 整型 | 有符号 32 位整数 | signed int |
unsigned int | 无符号整型 | 只能存正数 | uint |
size_t | 大小类型(用于内存/数组) | typedef 的无符号整型 | typedef unsigned int/long (依平台) |
二、范围与大小(取决于平台)
类型 | 32位系统(常见) | 64位系统(常见) |
---|---|---|
int | -2,147,483,648 ~ 2,147,483,647 | 同左 |
unsigned int | 0 ~ 4,294,967,295 | 同左 |
size_t | 0 ~ 4,294,967,295 | 0 ~ 18,446,744,073,709,551,615(64 位) |
size_t
的大小依赖于操作系统位宽,因为它用于表示 内存相关的对象大小(数组长度、分配内存大小等)。
三、区别总结
特性 | int | unsigned int | size_t |
---|---|---|---|
有无符号 | 有符号 | 无符号 | 无符号 |
能否为负数 | ✅ 是 | ❌ 否 | ❌ 否 |
应用场景 | 一般整数 | 不允许负值的计数 | 表示数组索引/内存大小等 |
类型别名 | - | - | typedef 由编译器定义 |
是否跨平台安全 | ⚠️ 不保证 | ⚠️ 不保证 | ✅ 跨平台推荐使用 |
四、应用场景
场景 | 推荐类型 | 原因 |
---|---|---|
计数器、ID 等不应为负的变量 | unsigned int | 防止负数错误 |
数组索引、内存大小(如 sizeof 返回值) | size_t | 与系统内存模型一致,跨平台 |
数学算法中需要正负 | int | 支持负值处理 |
五、代码示例
示例 1:数组遍历推荐使用 size_t
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4};
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << vec[i] << " ";
}
return 0;
}
理由:vec.size()
返回值是 size_t
,如果你用 int
去比较会产生隐式类型转换警告或溢出风险。
示例 2:unsigned int
与 int
比较错误示例
#include <iostream>
int main() {
unsigned int a = 1;
int b = -1;
if (a > b) // ⚠️ True! 因为 b 会被转为非常大的 unsigned int
std::cout << "a > b" << std::endl;
else
std::cout << "a <= b" << std::endl;
return 0;
}
输出是:a > b
,这是逻辑错误,因为 -1
被隐式转换为一个超大无符号数!
示例 3:使用 sizeof
正确类型
#include <iostream>
int main() {
int arr[10];
size_t size = sizeof(arr) / sizeof(arr[0]);
std::cout << "Array size: " << size << std::endl;
return 0;
}
sizeof
运算符返回的是 size_t
类型,因此用 size_t
接收是正确做法。
示例 4:负索引检查用 int
更安全
void access_array(int index) {
if (index < 0) {
std::cout << "Invalid index" << std::endl;
return;
}
// ...
}
如果用 unsigned int
定义 index,就无法判断 index < 0
,因为它永远不会小于零!
六、最佳实践总结
场景 | 推荐类型 |
---|---|
一般整数、含负值运算 | int |
不可能为负的计数、循环变量 | size_t (首选),或 unsigned int |
数组长度/索引 | size_t |
内存大小相关(如 malloc ) | size_t |
跨平台、跨架构开发 | 避免直接用 int / unsigned 做比较,尽量统一类型或强制转换 |
附加:如何避免 signed
/ unsigned
问题
- 避免
int < unsigned int
这种混比(可出错) - 使用
size_t
进行数组操作 - 尽量不将
size_t
与int
做比较,可用static_cast<size_t>(int_val)
强制类型匹配 - 开启
-Wall -Wextra
编译选项捕捉隐式转换警告