设为首页 加入收藏

TOP

深入理解C/C++数组和指针(二)
2019-06-12 16:06:14 】 浏览:110
Tags:深入 理解 C/C 指针
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

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ARTS 第一周打卡 下一篇c++ 【递归算法】梵塔问题

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目