指针

定义一个指向int的指针变量:

    int i = 100;
    int *p = &i;

以下代码将输出变量 i 的值:

# include <iostream>

using namespace std;

int main( int argc,char *argv[] )
{
    int i = 100;
    int *p = &i;

    cout << *p << endl;

    return 0;
}

对输出语句下断,调试运行,断下之后查看其反汇编代码:

10:       cout << *p << endl;
00401585   push        offset @ILT+195(std::endl) (004010c8)
0040158A   mov         ecx,dword ptr [ebp-8]
0040158D   mov         edx,dword ptr [ecx]
0040158F   push        edx
00401590   mov         ecx,offset std::cout (0047be90)
00401595   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
0040159A   mov         ecx,eax
0040159C   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)

其中,*p生成了58A-58D这两条汇编指令。

再来看看指向指针的指针解引用产生的代码:

11:       cout << **Ptr << endl;
0040158B   push        offset @ILT+195(std::endl) (004010c8)
00401590   mov         edx,dword ptr [ebp-0Ch]
00401593   mov         eax,dword ptr [edx]
00401595   mov         ecx,dword ptr [eax]
00401597   push        ecx
00401598   mov         ecx,offset std::cout (0047be90)
0040159D   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015A2   mov         ecx,eax
004015A4   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)

这下就产生了三条汇编指令,也就是说,*的出现次数N + 1就是产生汇编指令的条数。

定义一个指针指向char数组的首地址,并令其自增:

# include <iostream>

using namespace std;

int main( int argc,char *argv[] )
{
    char *p = "123";

    p++;

    return 0;
}

对自增操作下断,并查看反汇编:

9:        p++;
0040104F   mov         eax,dword ptr [ebp-4]
00401052   add         eax,1
00401055   mov         dword ptr [ebp-4],eax

自增操作将指针移动一个字节。

再定义一个指针指向int数组的首地址,并令其自增,查看其反汇编:

10:       p++;
0040105C   mov         ecx,dword ptr [ebp-0Ch]
0040105F   add         ecx,4
00401062   mov         dword ptr [ebp-0Ch],ecx

自增操作将指针移动四个字节,那我们就可以得出结论,指针自增移动的字节数 = 其指向的数据的字节数。

再来,定义一个数组指针指向一个数组:

# include <iostream>

using namespace std;

int main( int argc,char *argv[] )
{
    int arr[2] = { 1,2 };
    int (*ptr)[2] = ( int (*)[2] )arr;

    cout << **ptr << endl;

    return 0;
}

这段代码将输出数据首个元素1.

改动代码令数组指针自增:

# include <iostream>

using namespace std;

int main( int argc,char *argv[] )
{
    int arr[4] = { 1,2,3,4 };
    int (*ptr)[2] = ( int (*)[2] )arr;

    cout << *( *(ptr+1) ) << endl;

    return 0;
}

这段代码输出的结果又是什么呢?不急,我们先来查查输出语句的反汇编:

10:       cout << *( *(ptr+1) ) << endl;
0040159A   push        offset @ILT+195(std::endl) (004010c8)
0040159F   mov         ecx,dword ptr [ebp-14h]
004015A2   mov         edx,dword ptr [ecx+8]
004015A5   push        edx
004015A6   mov         ecx,offset std::cout (0047be90)
004015AB   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015B0   mov         ecx,eax
004015B2   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)

结果是指针移动了8个字节,是数组的第三个元素3.也就是说,数组指针移动的字节数 = 定义时[]里的N * 加上的数 * 定义时数据类型的字节数

这里,N为2,加上的数是1,int类型的字节为4.

2 * 1 * 4 = 8.

有了上面的知识,你可以尝试着猜猜这段程序输出的是什么:

# include <iostream>

using namespace std;

int main( int argc,char *argv[] )
{
    char *str = "123456789";
    char (*ptr)[3] = ( char (*)[3] )str;

    cout << *( *(ptr+2) + 1 ) << endl;

    return 0;
}

猜完了记得反汇编验证自己的想法。

原文地址:https://www.cnblogs.com/ZRBYYXDM/p/5228623.html