数组名和指针的区别

本文详细阐述了数组名和指针之间的区别,包括数组名的本质、数组名与指针的转换规则、指向数组的指针特点以及数组名作为函数参数时的行为变化。

许多程序员对数组名和指针的区别不甚明了,他们认为数组名就是指针,而实际上数组名和指针有很大区别,在使用时要进行正确区分,其区分规则如下:
 规则1 数组名指代一种数据结构,这种数据结构就是数组;
char str[10];
char *pStr = str;
cout << sizeof(str) << endl;
cout << sizeof(pStr) << endl;

  输出结果为:
 10
    4
  这说明数组名str指代数据结构char[10]。
   规则2 数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;
char str[10];
char *pStr = str;
str++; //编译出错,提示str不是左值 
pStr++; //编译正确

  规则3 指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址;

  规则4 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
例如:
void arrayTest(char str[])
{
cout << sizeof(str) << endl;   //输出指针长度
    str++; //编译正确
}
int main(int argc, char* argv[])
{
 char str1[10] = "I Love U";
 arrayTest(str1);
return 0;
}

<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、付费专栏及课程。

余额充值