数组元素首地址和数组首地址

本文详细解析了C语言中数组名、数组元素、数组首地址及它们之间的关系。通过实例展示了数组元素首地址和数组首地址的差异,以及地址运算后偏移量的不同。读者将理解arr、arr[0]、&arr[0]和&arr的区别,并掌握数组在内存中的表示方式。
int main()
{
	int arr[10] = {0};
	printf("数组元素首地址 :%d\n",arr);	//数组元素首地址   2293280
	printf("数组首地址 		:%d\n",&arr);	//数组首地址 	 2293280
	
	printf("数组元素首地址+1 :%d\n",arr+1);	//数组元素首地址  2293284
	printf("数组首地址+1 		:%d\n",&arr+1);	//数组首地址     2293320
	return 0;
}

arr、arr[0]、&arr[0]和&arr区别

  1. arr:数组名,同时也表示数组第一个元素的首字节地址,是一个常量值。
  2. arr[0]:数组一个元素,可以进行读写操作。
  3. &arr[0]:等价于arr,是一个地址常量,只能作为右值。
  4. &arr:数组首地址,其值与arr想等,但含义完全不同。&arr,是将整个数组作为一个新的数组类型,&arr就是这个类型对应内存空间的首地址。

所以,上述代码中,arr和&arr输出都为2293280,但是arr+1 输出为2293284,即在2293280基础上增加了4个字节(1×sizeof(int))。&arr+1输出为2293320,在2293280基础上增加了40个字节(10×sizeof(int))。

<think>我们讨论的是C/C++中数组的地址概念。用户之前问过关于`int(*)[10]`类型(指向数组的指针)的问题,现在他想了解一维数组首地址数组地址的区别。让我们澄清这两个概念。在C/C++中,数组名在大多数情况下会退化为指向其首元素的指针。但是,当我们取整个数组的地址时,得到的是指向整个数组的指针类型。举个例子:假设有数组`intarr[5];`-`arr`(或`&arr[0]`)是数组元素的地址,类型是`int*`。-`&arr`是整个数组的地址,类型是`int(*)[5]`。虽然这两个地址值相同(因为数组的起始地址元素的起始地址是同一个位置),但它们的类型不同,这会导致指针运算时的行为不同。具体差异:1.指针运算的步长:-`arr+1`:按照一个`int`的大小(例如4字节)增加,指向下一个元素(即arr[1])。-`&arr+1`:按照整个数组的大小(5*4=20字节)增加,指向下一个相同大小的数组(即跳过整个数组)。2.解引用:-`*arr`:得到首元素arr[0](类型int)。-`*(&arr)`:得到整个数组(类型int[5]),也就是数组名arr,它会退化为int*。我们通过代码示例来说明:示例代码:```c#include<stdio.h>intmain(){intarr[5]={1,2,3,4,5};printf("arr(首元素地址):%p\n",(void*)arr);printf("&arr[0]:%p\n",(void*)&arr[0]);printf("&arr(数组地址):%p\n",(void*)&arr);//注意:上面三个打印的地址值相同//指针运算的差异printf("arr+1:%p\n",(void*)(arr+1));//增加4(一个int大小)printf("&arr+1:%p\n",(void*)(&arr+1));//增加20(5*4=20)return0;}```输出可能类似于:```arr(首元素地址):0x7ffd2fbf6b60&arr[0]:0x7ffd2fbf6b60&arr(数组地址):0x7ffd2fbf6b60arr+1:0x7ffd2fbf6b64&arr+1:0x7ffd2fbf6b74```解释:-前三个地址相同。-`arr+1`比`arr`增加了4(因为一个int是4字节)->0x7ffd2fbf6b60+4=0x7ffd2fbf6b64。-`&arr+1`比`&arr`增加了20(整个数组大小)->0x7ffd2fbf6b60+20=0x7ffd2fbf6b74。因此,虽然地址值相同,但类型不同导致指针运算行为不同。另外,在函数参数传递中:-如果函数需要接收数组元素的地址,则参数类型为`int*`(或`int[]`,但实际会转换为指针)。-如果函数需要接收整个数组的地址(即指向数组的指针),则参数类型为`int(*)[5]`。总结:一维数组首地址(即首元素的地址)数组地址(即整个数组的地址)在数值上相同,但类型不同,因此进行指针运算时(如加1)的步长不同。相关问题:1.在函数中传递一维数组地址传递数组首地址有何区别?2.如何通过指向数组的指针来访问数组元素?3.为什么数组名作为函数参数传递时会失去其长度信息?4.使用指向数组的指针传递数组有何优点?</think> 在 C/C++ 中,**一维数组首地址****数组地址**虽然数值相同,但在类型语义上存在本质区别,主要体现在以下四个方面: ### 1. **类型本质差异** | **表达式** | **类型** | **语义** | **指针运算步长** | |------------|----------|----------|------------------| | `arr` | `int*` | **首元素地址** | `sizeof(int)` | | `&arr` | `int(*)[N]` | **整个数组的地址** | `N * sizeof(int)` | ```c int arr[5] = {10, 20, 30, 40, 50}; int *p1 = arr; // 首元素地址 (int*) int (*p2)[5] = &arr; // 数组地址 (int(*)[5]) // 指针运算验证(假设 int 占 4 字节) printf("%p\n", p1); // 0x1000 printf("%p\n", p1 + 1); // 0x1004 (步进 4 字节) printf("%p\n", p2); // 0x1000 printf("%p\n", p2 + 1); // 0x1014 (步进 20 字节 = 5*4) ``` > ✅ 虽然 `p1` `p2` 初始值相同,但 `+1` 操作步长不同,体现了类型系统的维度信息保留[^3] ### 2. **解引用行为对比** | **操作** | **首地址 `arr`** | **数组地址 `&arr`** | |----------|------------------|---------------------| | 解引用 | `*arr` → `arr[0]` (int 值) | `*&arr` → 数组名 `arr` (退化为 `int*`) | | 下标访问 | `arr[1]` | `(*&arr)[1]` | | 类型推导 | `sizeof(arr)` → `20` (整个数组) | `sizeof(*&arr)` → `20` (相同) | ```c printf("%d\n", *arr); // 10 (解引用首地址) printf("%d\n", (*&arr)[2]); // 30 (通过数组地址访问) ``` ### 3. **函数参数传递差异** ```c // 接收首地址(退化为指针) void func1(int *ptr) { for(int i=0; i<5; i++) ptr[i] *= 2; } // 接收数组地址(保留维度信息) void func2(int (*ptr)[5]) { for(int i=0; i<5; i++) (*ptr)[i] += 100; } func1(arr); // 传首地址 func2(&arr); // 传数组地址 ``` | 参数类型 | 优势 | 限制 | |----------|------|------| | `int*` | 通用性强 | 丢失数组长度信息[^1] | | `int(*)[5]` | 保留维度,防止越界 | 要求固定长度 `N`[^3] | ### 4. **内存布局与关系图** ```mermaid graph LR A[数组地址 &arr] -->|值为| B(0x1000) C[首元素地址 arr] -->|值为| B D[元素0 arr[0]] -->|地址| B E[元素1 arr[1]] -->|地址| F(0x1004) B --> E ``` > 关键结论: > **物理地址相同**:`&arr` ≡ `arr` ≡ `&arr[0]` > **逻辑类型不同**: > - `arr` 是标量指针(`int*`) > - `&arr` 是结构指针(`int(*)[5]`) > 差异在类型系统中通过步长维护 ### 常见误用示例 ```c int arr[3][4]; int **p = arr; // 错误!二维数组名实际是 int(*)[4] 类型 // 正确写法应保留列维度 int (*p)[4] = arr; // 合法 ``` --- ### ⁉️ 相关问题 1. 为什么二维数组名不能直接赋值给 `int**` 指针? 2. 函数参数 `void func(int arr[])` `void func(int* arr)` 有何等价关系? 3. 如何通过数组地址 `&arr` 计算数组总长度? 4. 动态分配内存时 `malloc(sizeof(&arr))` 为何错误?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值