当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

指针变量初始化 内存中怎么做的

    R.Ihskaka
    新手上路
    因为学校的机器没有linux,所以我用了xp+vc6,文件名为test.c

    代码是在Release模式下debug的,因为DEBUG模式会对环境有依赖.

    这个是源码:

    #include<stdio.h>
    #define SUCCESS 1
    #define FAILURE 0
    void main()
    {
    char *lpTest = "ABCD";
    printf("The String is: %s n ",lpTest);
    *(lpTest+1) = 'X';
    printf("The String is: %s n ",lpTest);
    }


    发表于: 2005-01-15 11:35


    在下新人,也想参与下讨论,哪里说的不对,请各位包涵并指出

    因为学校的机器没有linux,所以我用了xp+vc6,文件名为test.c

    代码是在Release模式下debug的,因为DEBUG模式会对环境有依赖.

    这个是源码:

    #include<stdio.h>
    #define SUCCESS 1
    #define FAILURE 0
    void main()
    {
    char *lpTest = "ABCD";
    printf("The String is: %s n ",lpTest);
    *(lpTest+1) = 'X';
    printf("The String is: %s n ",lpTest);
    }


    这是由vC6的Debug的汇编代码,其中带///////// 的为c代码,下面的是对应的汇编代码:

    ///void main() //这行自己加的,就从这里开始了
    {
    00401000 55 push ebp
    00401001 8B EC mov ebp,esp
    00401003 51 push ecx
    6: char *lpTest = "ABCD"; ////////////////
    00401004 C7 45 FC 30 70 40 00 mov dword ptr [lpTest],offset ___xt_z+8 (00407030)
    7: printf("The String is: %s n ",lpTest);////////////////
    0040100B 8B 45 FC mov eax,dword ptr [lpTest]
    0040100E 50 push eax
    0040100F 68 38 70 40 00 push offset ___xt_z+10h (00407038)
    00401014 E8 1F 00 00 00 call _printf (00401038)
    00401019 83 C4 08 add esp,8
    8: *(lpTest+1) = 'X';////////////////
    0040101C 8B 4D FC mov ecx,dword ptr [lpTest]
    0040101F C6 41 01 58 mov byte ptr [ecx+1],58h
    9: printf("The String is: %s n ",lpTest);////////////////
    00401023 8B 55 FC mov edx,dword ptr [lpTest]
    00401026 52 push edx
    00401027 68 50 70 40 00 push offset ___xt_z+28h (00407050)
    0040102C E8 07 00 00 00 call _printf (00401038)
    00401031 83 C4 08 add esp,8
    10: }
    00401034 8B E5 mov esp,ebp
    00401036 5D pop ebp
    00401037 C3 ret

    程序运行时,其实lpTest很明显是存放在堆栈里的(0x012ff7c) 从汇编上看到,lpTest开始时,push ecx,并将lpTest指向ecx寄存器的内容为地址的区域,在
    mov dword ptr [lpTest],offset ___xt_z+8 (00407030)
    后,lpTest才真正指向了定义的"ABCD".而这个"ABCD"的存放地址是0x00407030 . 可见赋值号右边的常量其实是开辟在一个单独的区域里,而且似乎所有的字符常量都是这样.在printf()里的"The String is: %s"也是存放在0x00407030之后的地址上,调用时push的.

    这样,对于lpTest本身来说,它其实就是变量而已,可以改变它指向的内容是很正常的.(不正常C语言早浮云了^_^ ) 而对于赋值号右边的字符串常量,它们是单独存放在一个区域的,指针依靠地址来使用他们.

    其实只要将 char *lpTest = "ABCD" 改为: const char *lpTest = "ABCD"
    就不可以再改变它的数值了.而加上const后的汇编代码,和没有加上时其实是一样的,"ABCD"仍然放在0x00407030. 只是如果你加了const,还试图改变lpTest的数值,那么编译时就会失败,这个看起来是由编译器保证的.这个我不能肯定,编译原理还没学,说不清楚 (>_<)

    那么如果是: const char Arry[]="WXYZ" 呢?

    00401000 55 push ebp
    00401001 8B EC mov ebp,esp
    00401003 83 EC 0C sub esp,0Ch
    8: const char Arry[]="WXYZ"; ////////////////
    00401006 A1 30 70 40 00 mov eax,[___xt_z+8 (00407030)]
    0040100B 89 45 F8 mov dword ptr [Arry],eax
    0040100E 8A 0D 34 70 40 00 mov cl,byte ptr [___xt_z+0Ch (00407034)]
    00401014 88 4D FC mov byte ptr [ebp-4],cl
    .........................

    其实还是一样,字符串常量都是开辟在0x00407030的,但是用了const,就会把这个地址的内容,拷贝到堆栈中去,然后利用
    mov cl,byte ptr [___xt_z+0Ch (00407034)]
    mov byte ptr [ebp-4],cl
    来调整一下,使Arry的地址精确指向堆栈中的4个字节,这样就是数组字符串常量了

 

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接