指针和数组的区别
我看到很多地方将数组介绍为指针。这在技术上是不正确的。数组不是指针。那么它是什么?它就像 C++ 中的任何其他变量一样。
看看这段代码
1 2
|
int arr[3]={3,4,5};
cout<<arr;
|
你可能会说:“看那里,arr 是一个地址,谁说它不是指针?”
我说:这段代码打印了一个地址。那么 var 是一个地址吗?
让我解释一下
所有变量都可以通过它们的地址在内存中进行操作。CPU 使用这些地址来获取它们、更改它们和保存它们。所以,所有变量都有一个地址(不仅仅是你指向的那些)。我们可以通过 (&) 运算符找到变量的地址,形式如下:
1 2
|
int* ptr=&intvar;
// Now the address of intvar is in ptr
|
数组只是一系列变量。但是有一个规则,C++ 将数组视为指针。这是什么意思?这意味着如果你写 arr,编译器会将其视为 &arr[0](除了我稍后会告诉你的三个条件),即数组第一个元素的地址。它的类型是“指向 T 的指针”,其中 T 是数组元素的类型(在本例中为 int)。如果你给它加 1,它将指向数组的第二个元素。
那么它会把 &arr 当作什么?
这是规则不适用的例外情况之一。它将其视为“指向数组的指针”。它仍然指向数组的第一个元素,但是如果你给这个指针加一,它将指向数组最后一个元素之后的内存地址(就像你跳过了整个数组一样)。它是一个指向整个数组的指针。&arr 和 arr 的值是相同的(第一个元素的地址)。但它们的类型不同。这里 &arr 的类型是“指向 T 数组的指针”(与 arr 的类型进行比较)。
看这个
1 2 3 4 5
|
int arr[3]={3,4,5};
cout<<"First element of the array: "<<arr[0] <<endl;
cout<<"Address of the first element: "<<&arr[0] <<endl;
cout<<"Address of the array: "<<arr <<endl;
cout<<"So what is this? "<<&arr <<endl;
|
第一个 cout:打印 arr[0] 的“值”。
第二个 cout:打印 arr[0] 的“地址”。
第三个 cout:再次打印 arr[0] 的“地址”。
第四个 cout:打印数组的地址,也就是 arr[0] 的地址。
还有这个
1 2 3 4 5
|
int arr[3]={3,4,5};
cout<<"First element of the array: "<<arr[0]+1 <<endl;
cout<<"Address of the first element: "<<&arr[0]+1 <<endl;
cout<<"Address of the array: "<<arr +1<<endl;
cout<<"So what is this? "<<&arr +1<<endl;
|
第一个 cout:打印 arr[0] 加一的“值”。
第二个 cout:打印 arr[1] 的“地址”。
第三个 cout:再次打印 arr[1] 的“地址”。
第四个 cout:打印数组之后第一个内存地址。
比较
相似之处,每个都有一个例子
1) (*) 可用于两者。
1 2 3 4 5 6 7 8
|
int arr[3]={1,3,4}; //Declares an array with 3 elements
int * ptr=arr; //Initialize pointer ptr with the address of array arr
cout<<*(arr+2)<<endl;
cout<<*{ptr+2)<<endl;
/* output */
4
4
|
2) 订阅(索引)可用于两者
1 2 3 4 5 6 7 8
|
int arr[3]={1,3,4}; //Declares an array with 3 elements
int * ptr=arr; //Initialize pointer ptr with the address of array arr
cout<<arr[2])<<endl;
cout<<ptr[2])<<endl;
/* output */
4
4
|
3) 指针可用作数组。
1 2 3 4 5 6 7
|
int *ptr=new int[3];
ptr[0]=12;
ptr[2]=3;
cout<<ptr[2];
/* output */
3
|
4) 数组可以具有指针类型。这意味着它的元素可以是指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
int ar[2]={8,2};
int var1=66;
int var2=111;
int* ptarray[5];
ptarray[0]=ar;
ptarray[1]=&ar[1]; //Address of second element of array ar
ptarray[2]=&var1;
ptarray[3]=&var2;
ptarray[4]=&ar[0];
// To keep code small I use a loop
for(int i=0;i<5;i++)
cout<<*(ptarray<i>)<<endl;
/* output */
8
2
66
111
8
|
5) 所有数组都将作为指针传递给函数,这意味着你实际上不能将数组发送到函数。所以 function(char[]) 等同于 function(char*)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include<iostream>
using namespace std;
void test(char v[]);
int main(){
char a[53];
//a="If a is an array, this line should generate an error";
test(pta);
return 0;
}
void test(char v[]){
v="If v is an array, this line should generate an error";
cout<<v<<endl;
}
|
不同之处
1) 指针是内存中的一个位置,它保存着另一个位置的地址,而数组是一个单一的、预先分配的连续元素块(所有类型都相同),大小和位置固定。
3) 数组不像指针那样可以在定义时初始化,但数组可以。
1 2
|
char car[3]={'a','b',66};
char* cpt=new char[3]; //No way to be initialized here.
|
4) 当我们为指针分配内存以用作动态数组时。内存以后可以调整大小或释放。但数组不是这样。
例如:
1 2 3
|
char* pta=new char[12];
//Using pta
delete[] pta;
|
3) 它们产生不同的汇编代码。看看并进行比较
1 2 3 4 5 6 7 8 9 10
|
int main()
{
char arr[3];
char* ptr=new char[3];
arr[0]='C'; //Assembly is for this.
ptr[0]='p'; //And for this.
return 0;
}
|
会有一个类似这样的汇编
1 2 3 4 5 6
|
arr[0]='C';
mov byte ptr [ebp-4],43h //The code for putting one character in an array
ptr[0]='p';
mov ecx,dword ptr [ebp-8] //The two line code for putting one character
mov byte ptr [ecx],70h //in a place where a pointer points to
|
希望有所帮助……
参考
http://67.40.109.61/torek/c/index.html
http://c-faq.com/questions.html