指针本身不携带数组长度信息,裸指针仅存储地址,无法通过sizeof获取实际数组长度;必须显式传入长度参数或使用边界标记。

指针本身不携带数组长度信息
在C++里,int* 或 char* 这类裸指针完全不知道它指向的内存有多大。编译器不会为指针额外存一个长度字段——它只存地址。所以你不能像 arr.size() 那样直接问指针“你管多少个元素”。常见错误是写 sizeof(ptr)/sizeof(*ptr),结果永远是 8/4=2(64位系统下)或 4/4=1(32位),跟实际数组长度毫无关系。
唯一可行的前提:传入长度参数或使用边界标记
如果你非要靠指针操作数组,必须让长度信息从外部来。最常见做法是把长度作为额外参数传进来:
void process_array(int* arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
// 安全访问 arr[i]
}
}或者用哨兵值(比如字符串末尾的 '\0'),但仅限于你能控制数据格式的场景(如C风格字符串)。对 int 数组,除非你约定好用某个特殊值(如 -1)作结束标记,否则没法自动推断长度。
替代方案:优先用 std::vector 或 std::array
现代C++里,裸指针遍历数组几乎总是设计信号:
立即学习“C++免费学习笔记(深入)”;
-
std::vector自带.size(),内存连续,可取.data()得到指针 -
std::array是栈上固定大小容器,.size()编译期可知,且支持sizeof正确计算 - 如果函数接口必须接受指针(如对接C API),那就明确要求调用方同时传长度——别试图从指针“猜”出来
容易被忽略的坑:函数形参退化问题
很多人以为写 void f(int arr[10]) 就能拿到长度,其实编译器会把它悄悄改成 void f(int* arr)。也就是说,连函数签名里的数字都是假的:
void bad_example(int arr[100]) {
static_assert(sizeof(arr) == sizeof(int*)); // ✅ 总是成立
// 这里 sizeof(arr) 不是 400,而是指针大小
}真正保留长度信息的只有两种情况:数组引用(int (&arr)[10])和模板推导(template<size_t n> void f(int (&arr)[N])</size_t>)。但这两种都不能用于运行时长度未知的场景——它们只对编译期确定大小的数组有效。
真实项目里,看到裸指针配循环,第一反应应该是检查有没有漏掉长度参数。靠指针自己“算长度”,基本等于在赌内存布局或硬编码。


















