数组名和指针的区别

转载链接:https://blog.youkuaiyun.com/findgeneralgirl/article/details/78501734

数组名和指针之间,经常会交替使用这两个变量,比如,把一个指针当成数组来使用,或者是把数组名赋值给指针,通过指针来访问数组成员变量,但是,数组名和指针之间到底有什么样的联系与区别,以及什么情况下该使用指针,什么情况下该使用数组名,我对这个做一个小小的解读。。
在这里插入图片描述
上图中,定义一个数组,数组名为arr,分别打印arr本身的地址,arr首元素的地址,以及arr本身,以整型形式输出,发现,这三者的值是相同的。这里说明了一下这种情况。
在这里插入图片描述
在说明这种情况之前,我们先了解一下变量的三要素:
红色圈代表:变量名称(如同人名。。)
绿色圈代表:该变量,即名为arr变量自己的地址。该地址存储了arr变量
蓝色圈代表:arr的值,为arr所指对象的地址。
所以一个普通变量arr!=&arr的,arr的值和arr自身的地址是不同的,指针变量就是一个类型为指针的普通变量。

而在上面的运行结果中,我们发现arr==&arr,这说明arr的地址就是arr,arr代表一个地址,arr本身就是一个地址,又根据arr==&arr[0]可知,arr是arr数组首元素的地址,所以arr作为数组名时,它的红圈,绿圈和篮圈代表的是同一个含义——数组首元素的地址。
这是数组名和指针不同的第一点:
数组名取地址得到的是数组名所指元素的地址。
对指针取地址得到的是指针变量自身的地址。

区别2:
数组是固定大小的,数组一经定义,那么数组名就是一个指向数组首元素类型的常量指针,也就是说数组名是不允许更改的,而指针可以更改。
数组名是常量指针,指针是变量指针。

区别3:
1.当对数组名使用sizeof时,得到的是数组元素的个数乘元素类型的字节数,对指针sizeof得到的是指针类型的字节数。
在这里插入图片描述

2.对数组名取&和对指针取&的意义不同。
在这里插入图片描述
上图可以看到对arr取地址后加1后,增大了36个字节,而对指针p取地址后加一,只增大了4个字节,所以说它们取地址后加一的能力不同。
这两种情况下,数组不再当成常量指针来使用。
总结:
1.数组名代表了一个指向数组首元素的常量指针,一经定义,不可更改,数组名作为常量指针,其类型与数组元素类型相同。指针是变量指针,定义之后仍可更改,其类型在定义时确定。

2.当出现sizeof,和&操作符时,数组名不再当成指向一个元素的常量指针来使用,而指针仍当成指向一个元素的变量指针来使用。

对于使用指针和数组下标的选择:
系统在使用数组下标对数组成员变量进行访问时,开销比较大,指针的访问效率是远远大于数组名的访问效率的。
但是只有在指针正确访问时,才成比下标法更有效率。
下标法更加容易理解,在可读性方面,也更加的具有优势,具体怎么选择,也没有一定的说法。

原文链接:https://blog.youkuaiyun.com/findgeneralgirl/article/details/78501734

<think>嗯,用户想了解C/C++中数组名指针区别。好的,这个问题我之前学过,但可能有些细节需要回忆一下。首先,我记得数组名在大多数情况下会被编译器转换为指向数组首元素的指针,但数组名本身并不是指针变量,而是一个常量指针。对吗? 根据引用内容,比如引用[1]提到,数组名会被编译器自动替换为指向首元素的指针,比如int arr[]的情况下,arr会被当作&arr[0]。所以当输出arrp的时候,地址是一样的。这说明数组名指针在某些情况下行为相似。但引用[3]里提到数组指针指向整个数组的地址,而数组名可能更接近首元素的地址?这里需要区分数组指针指针数组的不同。 然后,数组名是常量,不能被重新赋值,而指针是变量,可以指向其他地址。例如,像arr = another_array;这样的操作是非法的,而指针p可以指向其他地方。这点应该正确,用户可能需要知道这一点区别。 还有sizeof操作符的结果不同。对于数组名,sizeof返回整个数组的大小,而指针的话则是指针本身的大小,比如在64位系统上是8字节。引用中可能没有直接提到这点,但根据常识,这是关键区别之一。 另外,取地址操作符&的结果不同。对数组名使用&,得到的是整个数组的指针,类型是数组指针(比如int (*)[n]),而对指针变量使用&,得到的是指针变量的地址,类型是int**。引用[3]提到数组指针需要解引用才能访问元素,所以这部分可能相关。 类型信息方面,数组名保留了数组的类型长度信息,而指针只保存地址。例如,当传递数组名给函数时,它退化成指针,函数内部无法知道数组的长度,这也是为什么需要传递长度参数的原因。引用[5]中的例子显示,使用数组指针传递到函数时,可能需要解引用才能正确访问元素。 还有,数组名作为函数参数时会退化为指针。比如在函数参数中声明int arr[]其实等同于int* arr。这点引用中可能提到过,比如引用[1]中的编译器自动替换。 总结起来,数组名指针区别主要有:是否为常量、sizeof结果、&操作的结果、类型信息保留情况、以及作为函数参数时的退化行为。需要将这些点整理清楚,用例子说明,比如代码示例中的sizeof差异,或者尝试修改数组名的地址导致编译错误的情况。 可能还需要提到指针数组数组指针区别,但用户的问题主要是数组名指针的关系,所以这部分可能稍微带过。引用[5]中的例子展示了数组指针的使用,可以用来解释数组名指针的不同使用场景。 用户可能在实际编程中遇到数组名被当作指针使用的情况,但需要理解背后的原理,比如为什么不能对数组名进行赋值,或者为什么传递数组到函数后长度信息丢失。这些实际应用中的问题都需要在回答中覆盖。 最后,要确保引用的内容正确对应到各个区别点,比如引用[1]说明数组名被替换为指针,引用[3]说明数组指针的解引用方式,引用[5]中的代码示例展示数组指针的使用方法。结合这些引用内容,组织一个结构清晰的回答,分点列出区别,并给出代码示例注意事项。</think>### 数组名指针区别(C/C++) 在C/C++中,**数组名****指针**在语法上有相似行为,但本质存在重要区别。以下是核心差异的详细分析: --- #### 1. **本质属性不同** - **数组名**:是**常量标识符**,代表一段连续内存空间的起始地址,不可修改。例如: ```cpp int arr[5] = {1,2,3,4,5}; arr = nullptr; // 编译错误:数组名不可重新赋值[^1] ``` - **指针**:是**变量**,存储某个内存地址,可以重新指向其他地址。例如: ```cpp int* p = arr; p = &arr[2]; // 合法操作 ``` --- #### 2. **`sizeof` 运算结果不同** - **数组名**:`sizeof(arr)` 返回**整个数组占用的字节数**。例如: ```cpp int arr[5]; cout << sizeof(arr); // 输出 5*sizeof(int),如20(int为4字节时) ``` - **指针**:`sizeof(p)` 返回**指针变量本身的字节数**(如32位系统为4字节,64位系统为8字节)。 --- #### 3. **取地址操作(`&`)的语义** - **数组名**:`&arr` 的类型是**数组指针**(如 `int(*)[5]`),指向整个数组的地址。例如: ```cpp int arr[5]; int (*p_to_array)[5] = &arr; // 数组指针类型[^3] ``` - **指针**:`&p` 返回指针变量自身的地址,类型为 `int**`(二级指针)。 --- #### 4. **类型信息保留** - **数组名**:包含**数组长度元素类型**信息。例如: ```cpp void func(int arr[5]) { // 实际传递的是指针,数组长度信息丢失[^1] } ``` - **指针**:仅存储地址,无法直接推导指向内存的完整类型长度。 --- #### 5. **函数参数传递时的行为** - **数组名**:作为函数参数时,**退化为指向首元素的指针**。例如: ```cpp void Print(int *p) { /* 实际接收的是指针 */ } Print(arr); // 等价于 Print(&arr[0])[^5] ``` - **指针**:直接传递指针变量的值,行为一致。 --- #### 示例代码:数组名指针的对比 ```cpp #include <iostream> using namespace std; int main() { int arr[5] = {1,2,3,4,5}; int* p = arr; cout << "sizeof(arr): " << sizeof(arr) << endl; // 输出20(假设int为4字节) cout << "sizeof(p): " << sizeof(p) << endl; // 输出8(64位系统) cout << "arr+1地址偏移: " << (void*)(arr+1) - (void*)arr << endl; // 4字节(int大小) cout << "&arr+1地址偏移: " << (void*)(&arr+1) - (void*)&arr << endl; // 20字节(整个数组大小) return 0; } ``` --- ### 注意事项 1. **禁止对数组名赋值**:`arr = new int[5];` 是非法操作。 2. **多维数组的指针操作**:需使用数组指针(如 `int(*)[5]`)来正确访问元素。 3. **类型匹配**:数组指针与普通指针类型不兼容(如 `int(*)[5]` vs `int*`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值