9 pop esi
002E13DA pop ebx
002E13DB add esp,0D8h
002E13E1 cmp ebp,esp
002E13E3 call 002E113B
002E13E8 mov esp,ebp
002E13EA pop ebp
002E13EB ret
test2.cpp // 运行错误
extern char *s;
void test()
{
011F1470 push ebp
011F1471 mov ebp,esp
011F1473 sub esp,0D8h
011F1479 push ebx
011F147A push esi
011F147B push edi
011F147C lea edi,[ebp+FFFFFF28h]
011F1482 mov ecx,36h
011F1487 mov eax,0CCCCCCCCh
011F148C rep stos dword ptr es:[edi]
char ch;
int i=3;
011F148E mov dword ptr [ebp-14h],3
ch=s[i];
011F1495 mov eax,dword ptr ds:[011F7000h] /* ds没有影响,因为windows中所有的段基址都为0,取011F7000h单元的内容,这里是数组中前四个字节(指针是四个字节)组成的整数,也就是64636261h,也就是这里,把s所指的单元计算成了64636261h */
011F149A add eax,dword ptr [ebp-14h] /* 然后把地址和i相加,也就是64636261h+3,这个地址是未分配定义的,访问当然会出错 */
011F149D mov cl,byte ptr [eax] /* 访问错误 */
011F149F mov byte ptr [ebp-5],cl
return;
}
011F14A2 pop edi
011F14A3 pop esi
011F14A4 pop ebx
011F14A5 mov esp,ebp
011F14A7 pop ebp
011F14A8 ret
若test2.cpp中这样声明:
extern char s[];
这样就正确了,因为声明和定义一致,访问就没问题了。
所以千万不要简单的认为数组名与指针是一样的,否则会吃大亏,数组的定义和声明千万要保持一致性。
四、数组和指针的sizeof问题
数组的sizeof就是数组的元素个数*元素大小,而指针的sizeof全都是一样,都是地址类型,32位机器是4个字节。
下面给出一些例子:
测试程序:
#include<iostream>
using namespace std;
int main()
{
int a[6][8]={0};
int (*p)[8];
p=&a[0];
int (*pp)[6][8];
pp=&a;
cout<<sizeof(a)<<endl; // 192
cout<<sizeof(*a)<<endl; // 32
cout<<sizeof(&a)<<endl; // 4
cout<<sizeof(a[0])<<endl; // 32
cout<<sizeof(*a[0])<<endl; // 4
cout<<sizeof(&a[0])<<endl; // 4
cout<<sizeof(a[0][0])<<endl; // 4
cout<<sizeof(&a[0][0])<<endl; // 4
cout<<sizeof(p)<<endl; // 4
cout<<sizeof(*p)<<endl; // 32
cout<<sizeof(&p)<<endl; // 4
cout<<sizeof(pp)<<endl; // 4
cout<<sizeof(*pp)<<endl; // 192
cout<<sizeof(&pp)<<endl; // 4
system("pause");
return 0;
}
VS2010在32位windows7下的运行结果(VC6.0不符合标准):
192
32
4
32
4
4
4
4
4
32
4
4
192
4
下面对程序做逐一简单的解释:
(1) sizeof(a); a的定义为int a[6][8],类型是int [6][8],即元素个数为6*8的二维int型数组,它的大小就是6*8*sizeof(int),这里是192;
(2) sizeof(*a); *a这个表达式中数组名a被转换为指针,即数组第一个元素a[0]的地址,'*'得到这个地址所指的对象,也就是a[0],总的来说*a等价于*(&a[0]),a[0]的类型int [8],即大小为8的一维int型数组,它的大小就是8*sizeof(int),这里是32;
(3) sizeof(&a); '&'取a的地址,类型是int (*)[6][8],地址类型,这里大小是4;
(4) sizeof(a[0]); a[0]的类型int [8],即大小为8的一维int型数组,它的大小就是8*sizeof(int),这里是32;
(5) sizeof(*a[0]); *a[0]这个表达式中数组名a[0]被转换为指针,即数组的第一个元素a[0][0]的地址,'*'得到这个地址所指的元素,也就是a[0][0],总的来说*a[0]等价于*(&a[0][0]),a[0][0]的类型是int,它的大小就是sizeof(int),这里是4;
(6) sizeof(&a[0]); '&'取a[0]的地址,类型是int (*)[8],地址类型,这里大小是4;
(7) sizeof(a[0][0]); a[0][0]的类型是int,它的大小就是sizeof(int),这里是4;
(8) sizeof(&a[0][0]); '&'取a[0][0]的地址,类型是int *,地址类型,这里大小是4;
(9) sizeof(p); p的类型是int (*)[8],指向一个元素个数为8的int型数组,地址类型,这里大小是4;
(10)sizeof(*p); *p取得p所指的元素,类型是int [8],大小为8*sizeof(int),这里是32;
(11)sizeof(&p); '&'取p的地址,类型是int (**) [8],地址类型,这里大小是4;
(12)sizeof(pp); pp的类型是int (*)[6][8],指向一个大小为6*8的二维int型数组,地址类型,这里大小为4,
(13)sizeof(*pp); *pp取得pp所指的对象,类型是int [6][8],即元素个数为6*8的二维int型数组,它的大小就是6*8*sizeof(int),这里是192;
(14)size