C++ 指针和数组名一样吗 C++ sizeof结果不同的原因【基础】

7次阅读

数组名不是指针但可隐式转换为指针;sizeof(arr) 返回数组总字节,sizeof(p) 返回指针大小;仅当作为sizeof、&操作数或字符串初始化时数组名不退化。

C++ 指针和数组名一样吗 C++ sizeof结果不同的原因【基础】

数组名不是指针,但能隐式转成指针

数组名在大多数表达式中会“退化”为指向首元素的指针,但这只是隐式转换,不是它本来就是指针。比如 int arr[5]arr 本身是类型为 int[5] 的左值,不是 int*;只有在做算术、赋值给指针变量等场景下,编译器才自动把它转成 &arr[0]

一个关键证据:对数组名取地址——&arr 的类型是 int(*)[5](指向整个数组的指针),而 &arr[0]arr(退化后)的类型才是 int*。这两个地址数值相同,但类型和含义完全不同。

sizeof(arr) 和 sizeof(p) 结果不同的根本原因

sizeof 是编译期运算符,结果取决于操作数的**静态类型**,不关心运行时值。所以:

  • sizeof(arr)arr 类型是 int[5] → 结果是 5 * sizeof(int)(通常是 20)
  • sizeof(p)p 类型是 int* → 结果是该平台指针大小(通常是 4 或 8)
  • 即使写 int* p = arr;p 仍是纯指针,sizeof(p) 不会“记住”它曾指向数组

注意:sizeof 对函数参数里的数组形参也失效——因为形参 void f(int a[10]) 实际等价于 void f(int* a)sizeof(a) 永远是指针大小。

立即学习C++免费学习笔记(深入)”;

什么时候数组名不能退化成指针?

只有三种情况数组名保持原类型(不退化),此时 sizeof 才能拿到真实长度:

  • 作为 sizeof 的操作数(如 sizeof(arr)
  • 作为一元 & 的操作数(如 &arr
  • 作为字符串字面量初始化数组时(如 char s[] = "abc";sizeof(s) 是 4,含 ‘’)

其他所有地方——传给函数、参与加法、用在 if 判断里、赋值给指针变量——都会退化。这也是为什么 std::Arraystd::vector 更安全:它们把大小信息封装进类型或对象内,不会意外丢失。

容易踩的坑:用指针模拟数组时的 sizeof 误判

新手常写类似这样的代码:

void process(int* p) {     size_t n = sizeof(p) / sizeof(*p); // 错!n 永远是 1(或更糟,是 2/4/8)     // ... } int arr[100]; process(arr); // 传进去的是退化后的 int*

这会导致逻辑错误甚至越界访问。正确做法是显式传入长度:

  • 加一个 size_t len 参数
  • 改用 std::spanc++20)或 std::vector
  • 若必须用原始数组,只在定义作用域内用 sizeof(arr)/sizeof(arr[0])

真正的难点不在语法,而在于时刻意识到:数组名的“身份”在不同上下文中会切换,而 sizeof 是唯一能抓住它“本体”的工具——可惜它只在编译期有效,且极易被作用域和参数传递破坏。

text=ZqhQzanResources