以前上课的时候老师说,将数组名作为指针来使用,一直是这样认为。后来在论坛中看到其实是错的,不过不明其理,十一期间在网上发现了关于数组与指针的文章,将其翻译了,与大家共享(对使用的代码做了一点修改)。首次翻译文章,希望大家多多指点,谢谢!!
本文翻译至:http://www.cplusplus.com/forum/articles/10/
非常感谢那些有帮助的教程,我觉得有必要发表这篇关于指针和数组文章。不幸的是要从一些错误的观念恢复有点困难。所以正确和精确的理解问题是非常重要的,可以避免进一步的误解。
一个数组并不等于一个指针。在内存中,它是简单变量的序列。
当我们写:
- int array[3];
- array[2]=66;
C/C++编译器并不将array[0]看作是一个整型数值的地址,可以直接将它作为一个值,与下面的写法完全一样。
int var;
var=66;
明显的,var不是指针,同样的array[2]也不是指针。
但是,如果我们使用一个指针代替数组,对于同样的代码,不同的编译器所生成的汇编程序是不同的。例如:
- int *ptr = new int[3];
- ptr[2] = 66;
类似的,对于第一种代码,在编译器中没有不同的意思。第一中代码(第二行),编译器将会进行以下的步骤来生成的代码
1)转到array[0]的下面两个空间,并且使它等于66
在使用指针的代码中,它是这样的:
1)取得ptr[0]的值(地址)
2)给它加上2
3)将它所指向的值设为66
事实上,array、&array和&array[0]的值使相等的。但是&array是不同的类型(一个数组的内存地址而不是数组成员)
这里还有另外一个例子,使得你更容易理解这篇文章。我写了这样的程序:获取用户输入的一个值,给它加上4,最后将结果打印出来。我用整型指针和整型变量各写了一次。
使用整型变量:
- #include<iostream>
- int main(){
- int int_input;
- std::cin >> int_input;
- std::cout<< (int_input + 4) << std::endl;
- return 0;
- }
使用指针:
- #include<iostream>
- int main(){
- int *int_ptr = new int[1];
- std::cin >> *int_ptr;
- std::cout << (*int_ptr + 4) << std::endl;
- delete(int_ptr);
- return 0;
- }
有人认为这些程序是完全相同的吗?
让我们来看看它们的汇编代码。首先是整型变量的:
- 2212: main(){
- 00401000 push ebp
- 00401001 mov ebp,esp
- 00401003 sub esp,44h
- 00401006 push ebx
- 00401007 push esi
- 00401008 push edi
- 2213: int int_input;
- 2214: cin>>int_input;
- 00401009 lea eax,[ebp-4]
- 0040100C push eax
- 0040100D mov ecx,offset cin (00414c58)
- 00401012 call istream::operator>> (0040b7c0)
- 2215: cout<<(int_input+4)<<endl;
- 00401017 push offset endl (00401070)
- 0040101C mov ecx,dword ptr [ebp-4]
- 0040101F add ecx,4
- 00401022 push ecx
- 00401023 mov ecx,offset cout (00414c18)
- 00401028 call ostream::operator<< (0040b3e0)
- 0040102D mov ecx,eax
- 0040102F call ostream::operator<< (00401040)
- 2216: return 0;
- 00401034 xor eax,eax
- 2217: }
使用指针汇编代码
- 2212: main(){
- 00401000 push ebp
- 00401001 mov ebp,esp
- 00401003 sub esp,4Ch
- 00401006 push ebx
- 00401007 push esi
- 00401008 push edi
- 2213: int *int_ptr = new int[1];
- 00401009 push 4
- 0040100B call operator new (004011b0)
- 00401010 add esp,4
- 00401013 mov dword ptr [ebp-8],eax
- 00401016 mov eax,dword ptr [ebp-8]
- 00401019 mov dword ptr [ebp-4],eax
- 2214: cin>>*int_ptr;
- 0040101C mov ecx,dword ptr [ebp-4]
- 0040101F push ecx
- 00401020 mov ecx,offset cin (00414c38)
- 00401025 call istream::operator>> (0040b8a0)
- 2215: cout<< (*int_ptr + 4)<<endl;
- 0040102A push offset endl (004010a0)
- 0040102F mov edx,dword ptr [ebp-4]
- 00401032 mov eax,dword ptr [edx]
- 00401034 add eax,4
- 00401037 push eax
- 00401038 mov ecx,offset cout (00414bf8)
- 0040103D call ostream::operator<< (0040b4c0)
- 00401042 mov ecx,eax
- 00401044 call ostream::operator<< (00401070)
- 2216: delete(int_ptr);
- 00401049 mov ecx,dword ptr [ebp-4]
- 0040104C mov dword ptr [ebp-0Ch],ecx
- 0040104F mov edx,dword ptr [ebp-0Ch]
- 00401052 push edx
- 00401053 call operator delete (00401120)
- 00401058 add esp,4
- 2217: return 0;
- 0040105B xor eax,eax
- 2218: }
第19行对第32行。因此,你可以看出整数不同于“指向整数的指针”。一个整数是保存整数数据在内存空间,而一个整型指针是保存一个地址的内存空间。当要处理一个整数时,编译器知道这是一个内存空间的地址。我不打算解释这些汇编代码,因为这文章是针对初学者写的,我希望保持它的简短。