|
Array is not pointer
|
|
|
|
Last update on Feb 20, 2006 at 5:48am
|
|
(第一次想翻译点东西,就找了篇非常简单的文章来试一下。不试不知道,要想翻译一篇文章可是真不容易,翻译好久更困难了。可能你能读懂文章的意思,但是要想将其用中文再表达出来也不是那么容易。现在看来我翻译的的千疮百孔,漏洞百出。但这毕竟是第一次尝试,还请大家指正。)
非常感谢这些有用的材料,我觉得很有必要把这篇关于指针和数组的文章发表。然而不幸的是要想摆脱头脑中的一些错误想法有点困难。所以说正确并且精确的理解这些东西对避免将来犯错误是非常重要的。
数组不等于指针。它是内存中一些普通变量的序列。
当我们写下面的代码:
|
int array[3];
array[2]=666;
|
C/C++ 编译器并不把array[0]看作是一个整型变量的地址,而是直接把他看作一个值,就像下面代码一样:
显然我们知道 var 不是一个指针,所以array[2] 也不是。
但是如果我们用指针来代替数组,则代码看起来是一样的,但编译器却编译成不同的汇编代码。例如:
|
int *ptr = new int[3];
ptr[2] = 66;
|
这和第一段代码很像,但对编译器来说却意味着不同的意思。在第一段代码中第二条语句中,编译器生成的代码将做以下事情:
1) 指针下移两个位置并将其所指的值设为666
但是用指针的那段代码则是:
1、 取ptr[0]的地址;
2、 将其加2;
3、 将此地址指向的赋值为66。
实际上 "array"、"&array" 、"&array[0]"的值相等,但是"&array"的类型却是不同的,它是一个指向数组的地址而不是数组的元素。
为了让大家更好的理解,下面是另外一个例子。我想写一段程序使其从用户那里得到一个整型,将其加4,然后输出结果。一个用整型指针实现,一个用整型变量实现。
用整型变量的将是:
|
#include<iostream>
main(){
int int_input;
cin>>int_input;
cout<<(int_input + 4)<<endl;
return 0;
}
|
用整型指针的是:
|
#include<iostream>
main(){
int *int_ptr = new int[1];
cin>>*int_ptr;
cout<< (*int_ptr + 4)<<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 行你就会明白,一个整型变量和指向整型变量等指针是不同的。整型变量是一个存放整型数的内存位置,但是整型指针存的是整型数的内存地址的地址。编译器知道这个内存地址存放的是整型。因为这篇文章是面向初学者的并且为了简便,所以我不想解释这些汇编代码。
就像我刚才所说的数组是一系列的变量。从上面的例子可以看出,整型指针不是整型变量,所以它更不可能是一系列变量。
请写下您对本文章的评论。
英文原文如下:<http://www.cplusplus.com/articles/siavoshkc1.html>
|
Array is not pointer
|
|
Published by siavoshkc
|
|
Last update on
Feb 20, 2006 at 5:48am
|
|
With many thanks for these useful tutorials, I felt it's necessary to send this text about pointers and arrays. Unfortunately pulling out something wrong that is put in humans head is a bit difficult. So understanding the things correct and precise is very important to avoid further misconceptions.
An array is not equal to a pointer. It is a sequence of simple variables in memory.
When we write
|
int array[3];
array[2]=666;
|
C/C++ compiler doesn't see array[0] as an address to an integer value, it takes it directly as a value, exactly as same as writing
That's obvious that "var" is not a pointer exactly as array[2] is not.
But if we use a pointer instead of an array, the face of the code is the same but compiler generates different assembly code. For example
|
int *ptr = new int[3];
ptr[2] = 66;
|
Is similar to the first code but not with the same meaning to the compiler. In the first code (second line), compiler generates code that will do the following:
1) Go two places next of the array[0] and make it equal to 666.
But in code with pointer it is:
1) Fetch the value (address) of the ptr[0].
2) Add two to it.
3) Make the value pointed by it to 66.
Actually the value of "array", "&array" and "&array[0]" is equal. But the type of "&array" is different (a memory address to an array not an array member).
Here is another example to make the article more understanding. I want to write a program that gets an integer from user, adds 4 to it and then prints out the result. Once I write it using an integer pointer and once with an integer variable.
With integer it will be:
|
#include<iostream>
main(){
int int_input;
cin>>int_input;
cout<<(int_input + 4)<<endl;
return 0;
}
|
And using a pointer it will be:
|
#include<iostream>
main(){
int *int_ptr = new int[1];
cin>>*int_ptr;
cout<< (*int_ptr + 4)<<endl;
delete(int_ptr);
return 0;
}
|
Who thinks these programs are exactly the same?
Lets take a look at their assembly. For the first code with an integer it is:
|
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: }
|
And for the code with pointer it is:
|
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 lines Vs 32 lines. Therefore, you see, an integer is different to a "pointer to integer". An integer is a place of memory where an integer number is kept but an integer pointer (pointer to integer) is a place of memory where an address is saved. Compiler knows that is an address of a place of memory where an integer is held. I do not explain the assembly code since this article is for beginners and I want to keep it short.
As I said array is a sequence of variables in memory. In the example above, I concluded that a pointer is not an integer variable, so it is clear that it cannot be a sequence of them too.
Please feel free to send comments and your idea about the article.
发表于 @ 2007年04月25日 21:27:00|评论(loading...)|收藏