数组名在 sizeof 中不退化为指针,返回整个内存块大小;指针变量的 sizeof 返回指针自身大小(如64位系统为8字节);函数参数中数组声明实际退化为指针,sizeof 返回指针大小;数组名是不可修改的地址常量,而指针是可变变量;数组含完整类型与维度信息,指针不含长度元数据;字符串字面量初始化时,数组分配可修改副本,指针指向只读段,修改触发段错误;根本差异在于数组尺寸与类型编译期固化,指针值运行期可变。

数组名在 sizeof 中不退化为指针
这是最直接暴露底层差异的场景。sizeof 遇到真正的数组时,返回的是整个内存块大小;而遇到指针变量(哪怕它指向数组),返回的是指针本身大小(通常是 4 或 8 字节)。
-
int arr[10]:在函数内或全局作用域中,sizeof(arr)返回40(假设int为 4 字节) -
int *p = arr:无论p指向哪,sizeof(p)永远是8(64 位系统) - 函数参数写成
void f(int arr[10])并不改变本质——编译器把它当作void f(int *arr)处理,所以此时sizeof(arr)返回指针大小,不是 40
数组名是地址常量,不能被赋值或自增
数组名在表达式中多数时候“像”指针,但它不是变量,没有可修改的存储位置。编译器对它的处理是静态绑定到一段固定内存。
-
int arr[5]; arr = &x;→ 编译错误:arr不可赋值 -
arr++→ 编译错误:左值不是可修改的 lvalue -
int *p = arr; p++;→ 合法,p是变量,值可变 - 反例:外部声明
extern char *p;去引用定义为char p[100]的数组,会导致运行时把前几个字节当地址用,访问非法内存
数组有完整类型信息,指针没有维度和长度
编译器在符号表里为数组记录了元素类型、个数和总大小;指针只存类型和地址,不携带任何“长度”元数据。
-
int arr[3][4]的类型是int[3][4],&arr类型是int(*)[3][4] -
int (*p)[4] = arr;这里的p是数组指针,能正确算出行偏移;而int **pp = arr;会出错——arr不是int**,强行转换丢失维度信息 - 多维数组传参时若用
int **,必须手动管理行首地址数组;用int (*)[N]才能保持连续内存布局语义
初始化方式暴露存储本质差异
字符串字面量初始化时,数组和指针的内存分配行为完全不同。
-
char a[] = "hello";→ 在栈/数据段分配 6 字节,内容可改(如a[0] = 'H') -
char *p = "hello";→p存储的是只读段地址,p[0] = 'H'触发段错误(SIGSEGV) - 关键点:
a是数据副本,p是地址引用;前者有独立存储空间,后者只是别名
sizeof 行为分裂、函数传参退化、多维数组传递失败,全源于此。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











