C++函数内用数组指针实现Python len()获取数组长度结果异常
问题根因
你遇到的现象是C/C++的数组传参退化特性导致的:
- 在main函数中操作的
arr是完整的int[5]数组类型,&arr的类型为指向长度为5的int数组的指针int(*)[5],对其做+1操作时,地址偏移量为整个数组的大小(你测试中两个outside地址差为0x14即20字节,对应5个int的总大小),因此*(&arr +1) - arr计算得到的差值刚好是数组长度。 - 当数组作为参数传递给函数时,会自动退化为普通的int类型指针
int*,函数内的arrPtr是栈上独立存在的指针变量,和原数组没有绑定关系。此时&arrPtr取的是这个指针变量自身的栈地址,而非原数组的地址,对其+1仅偏移一个指针的大小(64位系统下为8字节),解引用后得到的是栈上的随机值,因此计算结果为随机数。
正确实现方案
方案1:模板推导(C++最推荐,编译期计算)
利用模板参数自动推导数组长度,参数传数组引用避免退化,完全无运行时开销,类型安全:
#include <iostream> using namespace std; template<typename T, size_t N> size_t len(T (&arr)[N]) { return N; } int main(){ int arr[] = {1,2,3,4,5}; size_t lenArr = len(arr); cout << "length of array: " << lenArr; return 0; }
如果传入普通指针作为参数,编译器会直接报错,避免误用。
方案2:宏实现(兼容C语言)
仅可在数组未退化的作用域内使用:
#define len(arr) (sizeof(arr) / sizeof(arr[0]))
注意:该宏不能在接收指针参数的函数内调用,否则会得到错误结果。
方案3:哨兵值实现(仅适用于允许特殊结尾标记的场景)
如果必须通过指针传参,可以约定数组末尾的哨兵值(如字符串的\0),遍历计数得到长度:
int len(int *arrPtr, int sentinel = 0) { int cnt = 0; while (arrPtr[cnt] != sentinel) cnt++; return cnt; } // 使用时需要给数组添加哨兵 // int arr[] = {1,2,3,4,5, 0};
该方案有运行时遍历开销,且会占用一个数组元素作为标记,仅适合特殊场景使用。
内容的提问来源于stack exchange,提问作者Suly Flachberger
相关产品推荐
相关产品推荐

