浅谈引用和指针,变量和常量

一、变量常量

变量:
狭义的变量定义:
    由用户定义的类型实例(有名字)
    for instance:
        int x = 12;
广义的变量定义:
    具有某种数据类型的存储空间(重点是存储空间)
    在包含狭义变量的定义外,还包括无名变量
    for instance:
        A::A();(A为类名)

常量:
即字面量
    for instance:
    “const”;
    45;
    ......

但我们通过反汇编结合思考可以看到:
    无论是常量还是变量都是我们根据编程语言规则在代码中的表象:
    {
        //.cpp
            //.class
            class A
            {
                int mm=12;
            }
            //.function
            main()
            {
                A a;
                A::A();
                int m0 = 12;
                char str[] = "variable";
            }

        ///////////////////////
        //a,m0,str为有名变量
        //{A::A()}为无名变量
        //12,"variable"为常量
    }

    //通过反汇编--->>:
    我们可以发现:
        源程序编译生成可执行文件(PE结构(.exe)):这不是重点,重点在于从这里可以看出程序中的数据及代码的数据存储类型(和单片机相似(其实就是windows的分段))

        源程序中的代码通过编译编码,其中的数据是分段存储的
        普遍认为windows的分段有:    堆,栈,代码段,数据段(这里不讨论bss)


        {
            #include<iostream>


            class A
            {
            public:
                A(int b) :mm(b){}
                int mm = 12;
            };


            int main()
            {
            00CD5280 55                   push        ebp  
            00CD5281 8B EC                mov         ebp,esp  
            00CD5283 81 EC 0C 01 00 00    sub         esp,10Ch  
            00CD5289 53                   push        ebx  
            00CD528A 56                   push        esi  
            00CD528B 57                   push        edi  
            00CD528C 8D BD F4 FE FF FF    lea         edi,[ebp-10Ch]  
            00CD5292 B9 43 00 00 00       mov         ecx,43h  
            00CD5297 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
            00CD529C F3 AB                rep stos    dword ptr es:[edi]  
            00CD529E A1 00 F0 CD 00       mov         eax,dword ptr ds:[00CDF000h]  
            00CD52A3 33 C5                xor         eax,ebp  
            00CD52A5 89 45 FC             mov         dword ptr [ebp-4],eax  
                char str[] = "dongguodongguo";
            00CD52A8 A1 1C CD CD 00       mov         eax,dword ptr ds:[00CDCD1Ch]  
            00CD52AD 89 45 E8             mov         dword ptr [str],eax  
            00CD52B0 8B 0D 20 CD CD 00    mov         ecx,dword ptr ds:[0CDCD20h]  
            00CD52B6 89 4D EC             mov         dword ptr [ebp-14h],ecx  
            00CD52B9 8B 15 24 CD CD 00    mov         edx,dword ptr ds:[0CDCD24h]  
            00CD52BF 89 55 F0             mov         dword ptr [ebp-10h],edx  
            00CD52C2 66 A1 28 CD CD 00    mov         ax,word ptr ds:[00CDCD28h]  
            00CD52C8 66 89 45 F4          mov         word ptr [ebp-0Ch],ax  
            00CD52CC 8A 0D 2A CD CD 00    mov         cl,byte ptr ds:[0CDCD2Ah]  
            00CD52D2 88 4D F6             mov         byte ptr [ebp-0Ah],cl  

                int mm = 100;
            00CD52D5 C7 45 DC 64 00 00 00 mov         dword ptr [mm],64h  
                const int mm0 = 100;
            00CD52DC C7 45 D0 64 00 00 00 mov         dword ptr [mm0],64h  
                int& yy = mm;
            00CD52E3 8D 45 DC             lea         eax,[mm]  
            00CD52E6 89 45 C4             mov         dword ptr [yy],eax  
                int *pp = &mm;
            00CD52E9 8D 45 DC             lea         eax,[mm]  
            00CD52EC 89 45 B8             mov         dword ptr [pp],eax  
                return 0;
            00CD52EF 33 C0                xor         eax,eax  
            .................
        }

        即我们在形成exe时,按照一定的格式形成:

        for instance:
            char str[] = "dongguodongguo";
            00CD52A8 A1 1C CD CD 00       mov         eax,dword ptr ds:[00CDCD1Ch

            这里常量“dongguodongguo”就是放在数据段的:ds(data segment)

        for instance:
            int mm = 100;
            00CD52D5 C7 45 DC 64 00 00 00 mov         dword ptr [mm],64h 

            这里的变量mm是在程序运行时在堆栈中动态形成的
            常量100则是放在代码段中,和指令一起存储



        由此:
            我们稍微总结下:

            变量(auto类型(没涉及堆)):
                在运行时的堆栈中生成

                【其实堆变量本质上一样(只是需要手动申请和释放)】

            常量:
                1.存储在数据段中
                2.和指令一起存储
                    可以推测下:一般也只有数字,字符随指令存储,串存储在数据段

        //高能............
        前面我们说过:--->>>>
                        变量是具有某种数据类型的存储空间(重点是存储空间)

        根据之前小结:变量和常量都存储在内存(只是分布段不同罢了)


        那变量和常量的区别又在哪?

        变量可以操作
        常量不可操作

            ----这是表象,那原因呢?


        其一:
            原来内存分段,方便操作系统管理调度的同时

            限制代码段一般为只读(保证程序的正确执行)

        其二:
            我们的编程语法限制了我们不能对常量进行操作
            大多数时候我们只能操作标识符(变量名),而常量无名

/////////////////////////////////////////////////////////////////////////////////////

    可能还有朋友对const,constexpr等修饰常量有疑惑

二、引用和指针

            const int mm0 = 100;
            mm0 = 12;
        1>d:\data\programming_c++\non_name_object\non_name_object\main.cpp(18): error C3892: “mm0”: 不能给常量赋值



            int mm = 100;
        00B152D5 C7 45 DC 64 00 00 00 mov         dword ptr [mm],64h  
            const int mm0 = 100;
        00B152DC C7 45 D0 64 00 00 00 mov         dword ptr [mm0],64h  


        通过对上面的观察,我们可以知道,所谓的const其实是编译层实现的“常量”(只读)权限(是可以强行破坏的)

        即const是语法层次的的限定


    引用和指针、
            int& yy = mm;
        011652E3 8D 45 DC             lea         eax,[mm]  
        011652E6 89 45 C4             mov         dword ptr [yy],eax  
            int *pp = &mm;
        011652E9 8D 45 DC             lea         eax,[mm]  
        011652EC 89 45 B8             mov         dword ptr [pp],eax  


        这里通过观察,发现引用和指针好像一样?

        但是通过反汇编可以发现:
            指针是变量,实惠被分配地址空间的
            引用就是一个标识符,在初始化前是不会被分配地址空间的

            这里就就不得不回忆下编译过程了
                变量的定义和声明大多数时候是一样的

                但是:
                    如extern int x;声明则有所不同
                    这里只是用户声明说有int型的x变量,只是表明存在这个东西,但具体在哪?还得看x的定义


                    所以如果我们将声明和定义分开来看时,声明只是标明了一个标识符(变量名),但是定义却同时为变量名关联了一块内存空间
                            ----->>>当然这都是编译器做的,所以我们或可以说定义包含声明

                            而引用则是对声明的应用:
                                一般而言,声明和定义没有区别,因为我们定义变量的同时也就声明了变量
                                定义时声明的变量是从堆栈中分配一块新的地址空间与标识符(变量名)进行关联
                                而引用就是一个标识符,我们在其初始化时,把用于初始化它的标识符所关联的地址空间与之关联

                                {
                                    int mm = 0;         //定义变量mm,同时分配地址空间,标识符mm关联0x3AFA60
                                    int &nn = mm;       //声明标识符nn,初始化nn,将mm关联的地址空间0x3AFA60与nn关联
                                }
                                //假设&mm == 0x3AFA60;

                                此时0x3AFA60这块地址空间同时关联上两个标识符 :mm和nn

                            so ...........
        *本人才疏学浅,如果有不足之处,还请各位大佬指点*

猜你喜欢

转载自blog.csdn.net/dong1528313271/article/details/79917905