为何C++中不能用&arr初始化int*指针?地址相同却报错
数组名、&数组名、&数组首元素的地址差异解析
核心原因:地址值相同,但类型完全不同
C语言是强类型语言,指针的类型决定了它的语义(比如指针加减时的步长),哪怕地址值一致,不同类型的指针也不能随意隐式转换。
arr的类型与转换:
在绝大多数表达式中,数组名arr会自动隐式转换为指向数组首元素的指针,也就是int*类型,指向arr[0]的地址。所以用它初始化int*指针完全合法。&arr[0]的类型:
这是直接取数组第一个元素的地址,类型本身就是int*,和int*指针类型完全匹配,自然可以直接初始化。&arr的类型:
这是取整个数组的地址,它的类型是int (*)[9](读作“指向包含9个int元素的数组的指针”)。虽然它的地址值和数组首元素地址完全相同,但这个指针的语义是指向整个数组——比如给它加1,它会跳过整整9个int的长度(步长为9 * sizeof(int)),而int*指针加1只会跳过1个int(步长为sizeof(int))。
编译器报错的本质
编译器禁止int (*)[9]隐式转换为int*,是为了避免你不小心写出逻辑错误的代码。比如如果强行转换:
int arr[9] = {1,2,3}; int* p2 = (int*)&arr; // 强制转换可以通过编译,但不推荐 int (*p_arr)[9] = &arr; // 这才是类型匹配的正确写法 // 对比指针加减的行为: printf("%d\n", *(p2 + 1)); // 输出2,符合int*的预期 printf("%d\n", *(int*)(p_arr + 1)); // 输出数组越界后的垃圾值,因为p_arr+1跳过了整个数组
简单说:地址值相同只是巧合(数组的起始地址同时是首元素和整个数组的地址),但指针的类型才是编译器关注的核心,不同类型的隐式转换会破坏类型安全,所以编译器直接报错。
内容的提问来源于stack exchange,提问作者Danhui Xu
相关产品推荐
相关产品推荐

