zoukankan      html  css  js  c++  java
  • 地址,指针和引用的表现形式

    1 必要知识

    地址:只有变量才有地址,常量没有地址,除了const定义的伪常量。

    指针(TYPE *):任何数据类型都可以定义指针,指针本身也是一种数据类型。由于指针保存的都是地址(32位操作系统下,地址为32位),所以无论什么类型的指针都占据4字节空间。

    引用(TYPE&):在C++中不能单独定义,定义就要初始化,是一个变量的别名。

    2.指针的工作方式

    2.1 指针寻址

    因为指针只保存首地址,使用类型修饰符修饰指针(TYPE *),能够解释这个地址中的数据类型,数据类型不同,占用的空间就不同。

    举例说明:

     1 #include <iostream>
     2 
     3 #pragma warning(disable:4996)
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     int Value = 0x12345678;
    10     int* iptr = &Value;
    11     char* cptr = (char*)& Value;
    12     short* sptr = (short*)& Value;
    13 
    14     printf("%08x
    ", *iptr);
    15     printf("%08x
    ", *cptr);
    16     printf("%08x
    ", *sptr);
    17 
    18     system("PAUSE");
    19     return 0;
    20 }

    数据在内存中的存储为"78 56 34 12","78"为首地址,

    指针iptr为int型指针,以int类型(4字节大小)对地址进行解释,以小端方式取出数据,"12345678"。指针cptr类似原理,取出1字节数据,"78"。指针sptr取出两字节数据,"5678"。

    同理,可以推理指针加法的工作方式。

    举例说明

     1 #include <iostream>
     2 
     3 #pragma warning(disable:4996)
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     int Value = 0x12345678;
    10     int* iptr = &Value;
    11     char* cptr = (char*)& Value;
    12     short* sptr = (short*)& Value;
    13 
    14     printf("%08x
    ", *iptr);
    15     printf("%08x
    ", *cptr);
    16     printf("%08x
    ", *sptr);
    17     printf("
    ");
    18     iptr += 1;
    19     cptr += 1;
    20     sptr += 1;
    21     printf("%08x
    ", *iptr);
    22     printf("%08x
    ", *cptr);
    23     printf("%08x
    ", *sptr);
    24 
    25     system("PAUSE");
    26     return 0;
    27 }

        iptr += 1;
    00735096  add         eax,4  
    00735099  mov         dword ptr [ebp-18h],eax  
        cptr += 1;
    0073509C  mov         eax,dword ptr [ebp-24h]  
    0073509F  add         eax,1  
    007350A2  mov         dword ptr [ebp-24h],eax  
        sptr += 1;
    007350A5  mov         eax,dword ptr [ebp-30h]  
    007350A8  add         eax,2  
    007350AB  mov         dword ptr [ebp-30h],eax

    通过汇编代码可以看出,指针加法也是根据指针类型进行解释。

    iptr+=1,向后推移4字节后,再以int型解释地址,输出数据。

    cptr+=,向后推移1字节后(首地址变成"56"),再以char型解释地址,取1字节数据,输出"56"。

    sptr类似... ...

    3.引用

    引用实际上是C++为了简化指针操作,对指针进行了封装,让使用者看不到存放地址的内存空间。

    举例说明

    int main()
    {
        int num = 0x12345678;
    
        int* iptr = &num;
        int& iref = num;
    
        return 0;
    }

    汇编代码

    int main()
    {
    00C016F0  push        ebp  
    00C016F1  mov         ebp,esp  
    00C016F3  sub         esp,0E8h  
    00C016F9  push        ebx  
    00C016FA  push        esi  
    00C016FB  push        edi  
    00C016FC  lea         edi,[ebp+FFFFFF18h]  
    00C01702  mov         ecx,3Ah  
    00C01707  mov         eax,0CCCCCCCCh  
    00C0170C  rep stos    dword ptr es:[edi]  
    00C0170E  mov         eax,dword ptr ds:[00C0A004h]  
    00C01713  xor         eax,ebp  
    00C01715  mov         dword ptr [ebp-4],eax  
    00C01718  mov         ecx,0C0C000h  
    00C0171D  call        00C011FE  
        int num = 0x12345678;
    00C01722  mov         dword ptr [ebp-0Ch],12345678h  
    
        int* iptr = &num;
    00C01729  lea         eax,[ebp-0Ch]  
    00C0172C  mov         dword ptr [ebp-18h],eax  
        int& iref = num;
    00C0172F  lea         eax,[ebp-0Ch]  
    00C01732  mov         dword ptr [ebp-24h],eax  
    
        return 0;
    00C01735  xor         eax,eax  
    }

    4.常量

    常量数据在程序运行之前就已经存在了。可以使用#define或者const来定义常量。

    举例说明

    int main()
    {
        const char* str = "Reverse!";
    
        return 0;
    }

    #define是一个真常量,而const是由编译器判断实现的常量,是一个假常量。在编译器进行检查时,发现const定义的变量一个常量值,会将程序中所有该变量替换为常量值。

    举例说明

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        const int num = 0x12345678;
    
        int* ptr = (int*)& num;
    
        *ptr = 0x2;
    
        int count = num;
    
        printf("%08x
    ", num);
        printf("%08x
    ", *ptr);
    
        system("PAUSE");
        return 0;
    }

    由于编译器提前替换了num,所以我们在改变常量值后输出num依然是更改前的值,而ptr指向的是现在内存中的常量值。

  • 相关阅读:
    Java8之Consumer接口
    Java8之Cloneable接口
    Java基础之Iterator接口
    Java基础之Iterable接口
    WPF中窗体在同一个位置实现不同页面切换
    WPF中单选框RadioButton
    WPF中的TextBlock处理长字符串
    WPF中Canvas使用
    WPF中窗体调用窗体
    WPF中HyperLink超链接的使用
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11564803.html
Copyright © 2011-2022 走看看