关于堆,栈,动态分配,静态分配的一个小实验

关于堆,栈,动态分配,静态分配的一个小实验

其中有些不明白,大家帮着解释一下

下边是c源码
char *str_g="abcd";
int a=0;
int b;
int main()
{
        static int c;
        char *str_l=(char *)malloc(16);
        c=b=a;
        printf("address of str_l=%x/n",&str_l);
        printf("address of malloc string=%x/n",str_l);
}

gerysand    2005-4-15 04:51
关于堆,栈,动态分配,静态分配的一个小实验

编译后的汇编    
         .file   "test.c"        //指出这个文件由test.c编译而来
        .section        .rodata //只读段包含字符"abcd"
.LC0:
        .string "abcd"
                                                                                                                                              
.globl str_g            //全局变量str_g
        .data           //表明在数据段中
        .align 4
        .type   str_g, @object
        .size   str_g, 4
str_g:
        .long   .LC0    //初始化为.LC0的地址,即"abcd"字符串的地址
.globl a                //全局变量a
        . bss            //为什么它放在 bss数据段中?(还是我理解的有问题)
        .align 4
        .type   a, @object
        .size   a, 4
a:
        .zero   4       //长度为4个字节,初始化为0(是这个意思吗?)
        .local  c.0     //用local标记的 static变量c,这个是static定义所特有的,表示虽然放在全局区域但是不可导出
        .comm   c.0,4,4 //用comm标记应该是表示未初始化,但是后边0,4,4表示什么无从考证
        .section        .rodata //又是两个字符串常量,用rodata标记为只读数据段
.LC1:
        .string "address of str_l=%x/n" //.LC1长度为21byte
.LC2:
        .string "address of malloc string=%x/n"
        .text
.globl main             //全局函数入口
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        subl    %eax, %esp
        subl    $12, %esp
        pushl   $16
        call    malloc
        addl    $16, %esp
        movl    %eax, -4(%ebp)
        movl    a, %eax
        movl    %eax, b
        movl    %eax, c.0
        subl    $8, %esp
        leal    -4(%ebp), %eax
        pushl   %eax
        pushl   $.LC1
       call    printf
        addl    $16, %esp
        subl    $8, %esp
        pushl   -4(%ebp)
        pushl   $.LC2
        call    printf
        addl    $16, %esp
        leave
        ret
        .size   main, .-main    //计算main的大小
        .comm   b,4,4           //为什么b放在这里定义???难道它是放在text段里吗???comm应该是指未初始化
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.3.2 20031022 (Red Hat Linux 3.3.2-1)"


用bojdump -d 查看的.o文件

test.o:     文件格式 elf32-i386
                                                                                                                                              
反汇编 .text 节:
                                                                                                                                              
00000000 <main>;:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   83 e4 f0                and    $0xfffffff0,%esp
   9:   b8 00 00 00 00          mov    $0x0,%eax
   e:   29 c4                   sub    %eax,%esp
  10:   83 ec 0c                sub    $0xc,%esp
  13:   6a 10                   push   $0x10
  15:   e8 fc ff ff ff          call   16 <main+0x16>;
  1a:   83 c4 10                add    $0x10,%esp
  1d:   89 45 fc                mov    %eax,0xfffffffc(%ebp)
  20:   a1 00 00 00 00          mov    0x0,%eax
  25:   a3 00 00 00 00          mov    %eax,0x0
  2a:   a3 04 00 00 00          mov    %eax,0x4
  2f:   83 ec 08                sub    $0x8,%esp
  32:   8d 45 fc                lea    0xfffffffc(%ebp),%eax
  35:   50                      push   %eax
  36:   68 05 00 00 00          push   $0x5  //对应.LC1
  3b:   e8 fc ff ff ff          call   3c <main+0x3c>;
//为什么一样的二进制代码和下一个printf调用翻译出来的汇编不一样???见4e地址处
//用objdump -r 查看了一下,发现printf是需要重定位的,但是应该重定向到同一位置
//为什么会出现地址不一样的情况,请高手解答
  40:   83 c4 10                add    $0x10,%esp
  43:   83 ec 08                sub    $0x8,%esp
  46:   ff 75 fc                pushl  0xfffffffc(%ebp)
  49:   68 1a 00 00 00          push   $0x1a //对应.LC2,和LC1相差21byte
  4e:   e8 fc ff ff ff          call   4f <main+0x4f>;
  53:   83 c4 10                add    $0x10,%esp
  56:   c9                      leave
  57:   c3                      ret


*/

从中学习到了 static 声明的变量,不管它是全局变量也好,还是在函数之中的也好,只要是没有赋初值
都存放在. bss段,如果赋了初值,则把它放在.data段。

反汇编的方法, 首先
gcc -o  test.o  -c  test.c
得到test.o文件,然后,objdump -d test.o  即可

变量
的逻辑存储空间
2007-10-23 13:05

1.static和全局变量:存放在静态存储区,可能是.bss段或者.data段
     已出始化:.data段
     未初始化:.bss段(注:bss是Block Started by Symbol的缩写)

2.auto变量:栈

3.register变量:如果优化成功,放入cpu的寄存器;否则,与auto变量相同。



23、static的使用
————————
static关键字,表示了“静态”,一般来说,他会被经常用于变量和函数。一个static的
变量,其实就是全局变量,只不过他是有作用域的全局变量。比如一个函数中的static变
量:
  
char*
getConsumerName()
{
    static int cnt = 0;
  
    ....
    cnt++;
    ....
}
  
  
cnt变量的值会跟随着函数的调用次而递增,函数退出后,cnt的值还存在,只是cnt只能在
函数中才能被访问。而cnt的内存也只会在函数第一次被调用时才会被分配和初始化,以后
每次进入函数,都不为static分配了,而直接使用上一次的值。
  
对于一些被经常调用的函数内的常量,最好也声明成static(参见第12条)
  
但static的最多的用处却不在这里,其最大的作用的控制访问,在C中如果一个函数或是一
个全局变量被声明为static,那么,这个函数和这个全局变量,将只能在这个C文件中被访
问,如果别的C文件中调用这个C文件中的函数,或是使用其中的全局(用extern关键字)
,将会发生链接时错误。这个特性可以用于数据和程序保密。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值