程序员面试宝典中的关于指针的题

1、下面的程序运行时哪里会出现错误: 

struct s 



    int i; 

    int * p; 

}; 

  

int main() 



    s s; 

    int * p = &s.i; 

    p[0] = 4; 

    p[1] = 3; 

    s.p = p; 

    s.p[1] = 1; 

    s.p[0] = 2; 

  

    return 0; 



 

 

【题目解析】 

这道题考的是对结构体内存使用情况的理解。在32位的操作系统中,int和指针类型的变量占用空间都是4个字节。在本题中 &s.i的值实际就是 &s的值,所以“int * p = &s.i”也就相当于把p指向了结构体s的地址的起始位置。

假设 &s的值为0x12300,则p的值也是0x12300,p[0]指的是从0x12300开始的连续4个字节的空间,p[1]指的是从0x12304(注意!不是0x12301)开始的连续4个字节的空间。这样,p[0]也就相当于s.i,p[1]也就相当于s.p,分析到这一步,可以确定程序运行到“s.p=p;”这里不会出错。继续往下看。 

在进行了“s.p=p;”的赋值之后,s.p指向的是s的首地址,此时s.p[0]相当于s.i,s.p[1]相当于s.p。 

下一句“s.p[1]=1”执行过之后,此时s.p的值为1,也就是指向内存的0x00001处,隐患出现了。在执行“s.p[0]=2”的时候,实际上是向内存0x00001起始的连续四个字节写入0x00000002,而那块内存不属于这个程序,会出现访问非法内存的错误。 

vc解析的汇编代码如下(部分),有兴趣的可以参考一下。 

;   14:       s s; 

;   15:       int * p = &s.i; 

00401028    lea         eax,[ebp-8] 

0040102b    mov         dword ptr [ebp-0ch],eax 

;   16:       p[0] = 4; 

0040102e    mov         ecx,dword ptr [ebp-0ch] 

00401031    mov         dword ptr [ecx],4 

;   17:       p[1] = 3; 

00401037    mov         edx,dword ptr [ebp-0ch] 

0040103a    mov         dword ptr [edx+4],3 

;   18:       s.p = p; 

00401041    mov         eax,dword ptr [ebp-0ch] 

00401044    mov         dword ptr [ebp-4],eax 

;   19:       s.p[1] = 1; 

00401047    mov         ecx,dword ptr [ebp-4] 

0040104a    mov         dword ptr [ecx+4],1 

;   20:       s.p[0] = 2; 

00401051    mov         edx,dword ptr [ebp-4] 

00401054    mov         dword ptr [edx],2 


总结:p是一个指针,那么p的值为地址,*p,p[0]为该地址对应空间的值。p[1]为该地址对应下一个空间的值,首地址间隔与指针p的类型有关。

s.p中的p 和结构体外部的p不是一个p.


你可能感兴趣的:(面试,汇编)