• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            elva

            轉(zhuǎn):全局變量、靜態(tài)變量和局部變量

             
            一、預(yù)備知識(shí)—程序的內(nèi)存分配
            一個(gè)由c/C++編譯的程序占用的內(nèi)存分為以下幾個(gè)部分
            1、棧區(qū)(stack)— 由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
            2、堆區(qū)(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表。
            3、全局區(qū)(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域(.data),未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域(.bss)。 - 程序結(jié)束后由系統(tǒng)釋放。
            4、文字常量區(qū) —常量字符串就是放在這里的(.rodata)。 程序結(jié)束后由系統(tǒng)釋放。
            5、程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼(.text)。
             
            二、例子程序
            這是一個(gè)前輩寫的,非常詳細(xì)
            //main.cpp
            int a = 0;          // 全局初始化區(qū)
            char *p1;           // 全局未初始化區(qū)
            main()
            {
              int b;            // 棧區(qū)
              char s[] = "abc"; // 棧區(qū)
              char *p2;         // 棧區(qū)
              char *p3 = "123456";     // "123456\0" 在常量區(qū),p3在棧區(qū)
              static int c =0;         // 全局(靜態(tài))初始化區(qū)
             
              p1 = (char *)malloc(10);
              p2 = (char *)malloc(20); // 分配得來的10和20字節(jié)的區(qū)域就在堆區(qū)
             
              strcpy(p1, "123456");    // "123456\0" 放在常量區(qū),編譯器可能會(huì)將它
                                          // 與p3所指向的"123456"優(yōu)化成一個(gè)地方。
             
             ============================================================== 
            static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?
            static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?   
            :
            1) 
            全局變量(外部變量)的說明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲(chǔ)方式, 靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲(chǔ)方式。 這兩者在存儲(chǔ)方式上并無不同。這兩者的區(qū)別在于非靜態(tài)全局變量的作用域是整個(gè)源程序, 當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),非靜態(tài)的全局變量在各個(gè)源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此可以避免在其它源文件中引起錯(cuò)誤。
            2) 從以上分析可以看出, 把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲(chǔ)方式即改變了它的生存期。把全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域,限制了它的使用范圍。                   
            3) static
            函數(shù)與普通函數(shù)作用域不同,僅在本文件。只在當(dāng)前源文件中使用的函數(shù)應(yīng)該說明為內(nèi)部函數(shù)(static),內(nèi)部函數(shù)應(yīng)該在當(dāng)前源文件中說明和定義。對(duì)于可在當(dāng)前源文件以外使用的函數(shù),應(yīng)該在一個(gè)頭文件中說明,要使用這些函數(shù)的源文件要包含這個(gè)頭文件   

            綜上所述:
            static
            全局變量與普通的全局變量有什么區(qū)別:

            static全局變量只初使化一次,防止在其他文件單元中被引用  
            static局部變量和普通局部變量有什么區(qū)別:
            static局部變量只被初始化一次,下一次依據(jù)上一次結(jié)果值;   
            static函數(shù)與普通函數(shù)有什么區(qū)別:
            static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個(gè)被調(diào)用中維持一份拷貝
             
             ==============================================================
            一個(gè)C語(yǔ)言變量分配的實(shí)際例子:
             
              我們來看看在可執(zhí)行文件中,變量們會(huì)被分配在哪些區(qū)里.這里以可執(zhí)行文件為例子,可執(zhí)行文件有固定的內(nèi)存加載地址,符號(hào)(函數(shù)/變量的名字)將來在內(nèi)存里的地址連接器是可以提前確定的。
             
              源程序編譯連接的結(jié)果是形成1堆匯編指令代碼,大致分為.text .data .bss等幾個(gè)節(jié)區(qū)(section)。對(duì)于.exe文件和.so文件,全局和靜態(tài)變量都放在.data 或.bss段(gas把源文件從頭到尾掃描1遍,才知道一個(gè)變量的全部情況:是否定義;類型;是否初始化。然后把初始化的變量在.data段里分配位置和空間,把沒初始化的變量在.bss段里分配位置和空間,沒定義的變量分配在.undef段)。匯編指令代碼里全局變量表現(xiàn)為一個(gè)內(nèi)存地址(全局變量在目標(biāo)文件里是一個(gè)偏移值,加載進(jìn)內(nèi)存里是一個(gè)內(nèi)存地址)。臨時(shí)變量在匯編代碼里變成ebp/esp+n,表現(xiàn)為一個(gè)堆棧地址,化為程序正文(.text)的一部分。有些變量的最終內(nèi)存地址在加載進(jìn)內(nèi)存之前還不能確定,需要加載進(jìn)內(nèi)存才可以計(jì)算出來.
              全局變量 作用域是跨越多個(gè)源程序的。因此全局變量不能重名。靜態(tài)變量作用域是位于單個(gè)源程序內(nèi)。多個(gè)源程序可以有同名的全局靜態(tài)變量。本例中,為了區(qū)分多個(gè)同名的靜態(tài)變量,gcc 用 c444和c444.0 來加以區(qū)別。
             
            [test@redhat]# more aaa.c
            # include <stdio.h>
            int a111 = 0;              # 全局變量 已初始化
            char *p111 = "654321";     # 全局指針變量 已經(jīng)初始化
            static int c444 = 9;       # 靜態(tài)全局變量 已經(jīng)初始化
            static int c555;           # 靜態(tài)全局變量 未初始化
            main() 

                int b222;              # 局部變量
                char s333[] = "abc";   # 局部變量
                char *p222;            # 局部變量
                char *p333 = "123456";    # 局部變量
                static int c444 =0;       # 已初始化靜態(tài)局部變量,與前面靜態(tài)全局變量重名
                p111 = (char *)malloc(10); 
                p222 = (char *)malloc(20);
                strcpy(p111, "123456");
            }

            [test@redhat]# gcc -o aaa ./aaa.c
             
            [test@redhat]# readelf -a ./aaa
            ELF Header:
              Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
              Class:                             ELF32
              Data:                              2's complement, little endian
              Version:                           1 (current)
              OS/ABI:                            UNIX - System V
              ABI Version:                       0
              Type:                              EXEC (Executable file)
              Machine:                           Intel 80386
              Version:                           0x1
              Entry point address:               0x80482d0
              Start of program headers:          52 (bytes into file)
              Start of section headers:          2040 (bytes into file)
              Flags:                             0x0
              Size of this header:               52 (bytes)
              Size of program headers:           32 (bytes)
              Number of program headers:         7
              Size of section headers:           40 (bytes)
              Number of section headers:         27
              Section header string table index: 24
            Section Headers:   Addr是文件加載進(jìn)內(nèi)存時(shí),每個(gè)section在內(nèi)存中的虛擬地址
              [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
              [ 0]                   NULL            00000000 000000 000000 00      0   0  0
              [ 1] .interp           PROGBITS        08048114 000114 000013 00   A  0   0  1
              [ 2] .note.ABI-tag     NOTE            08048128 000128 000020 00   A  0   0  4
              [ 3] .hash             HASH            08048148 000148 00002c 04   A  4   0  4
              [ 4] .dynsym           DYNSYM          08048174 000174 000060 10   A  5   1  4
              [ 5] .dynstr           STRTAB          080481d4 0001d4 000053 00   A  0   0  1
              [ 6] .gnu.version      VERSYM          08048228 000228 00000c 02   A  4   0  2
              [ 7] .gnu.version_r    VERNEED         08048234 000234 000020 00   A  5   1  4
              [ 8] .rel.dyn          REL             08048254 000254 000008 08   A  4   0  4
              [ 9] .rel.plt          REL             0804825c 00025c 000018 08   A  4   b  4
              [10] .init             PROGBITS        08048274 000274 000017 00  AX  0   0  4
              [11] .plt              PROGBITS        0804828c 00028c 000040 04  AX  0   0  4
              [12] .text             PROGBITS        080482d0 0002d0 0001e4 00  AX  0   0 16
              [13] .fini             PROGBITS        080484b4 0004b4 00001b 00  AX  0   0  4
              [14] .rodata           PROGBITS        080484d0 0004d0 00001a 00   A  0   0  4
              [15] .eh_frame         PROGBITS        080484ec 0004ec 000004 00   A  0   0  4
              [16] .data             PROGBITS        080494f0 0004f0 00001c 00  WA  0   0  4
              [17] .dynamic          DYNAMIC         0804950c 00050c 0000c8 08  WA  5   0  4
              [18] .ctors            PROGBITS        080495d4 0005d4 000008 00  WA  0   0  4
              [19] .dtors            PROGBITS        080495dc 0005dc 000008 00  WA  0   0  4
              [20] .jcr              PROGBITS        080495e4 0005e4 000004 00  WA  0   0  4
              [21] .got              PROGBITS        080495e8 0005e8 00001c 04  WA  0   0  4
              [22] .bss              NOBITS          08049604 000604 000008 00  WA  0   0  4
              [23] .comment          PROGBITS        00000000 000604 000126 00      0   0  1
              [24] .shstrtab         STRTAB          00000000 00072a 0000ce 00      0   0  1
              [25] .symtab           SYMTAB          00000000 000c30 0004c0 10     26  2f  4
              [26] .strtab           STRTAB          00000000 0010f0 000275 00      0   0  1
            Program Headers:
              Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
              PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
              INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
                  [Requesting program interpreter: /lib/ld-linux.so.2]
              LOAD           0x000000 0x08048000 0x08048000 0x004f0 0x004f0 R E 0x1000
              LOAD           0x0004f0 0x080494f0 0x080494f0 0x00114 0x0011c RW  0x1000
              DYNAMIC        0x00050c 0x0804950c 0x0804950c 0x000c8 0x000c8 RW  0x4
              NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
              STACK          0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
             
            Symbol table '.symtab' contains 76 entries:
            對(duì)于.exe文件,符號(hào)的Value 是將來加載進(jìn)內(nèi)存中的真實(shí)地址;對(duì)于.so文件Value需要重定位.
               Num:    Value  Size Type    Bind   Vis      Ndx Name
                 0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
                 1: 08048114     0 SECTION LOCAL  DEFAULT    1 
                 2: 08048128     0 SECTION LOCAL  DEFAULT    2 
                 3: 08048148     0 SECTION LOCAL  DEFAULT    3 
                 4: 08048174     0 SECTION LOCAL  DEFAULT    4 
                 5: 080481d4     0 SECTION LOCAL  DEFAULT    5 
                 6: 08048228     0 SECTION LOCAL  DEFAULT    6 
                 7: 08048234     0 SECTION LOCAL  DEFAULT    7 
                 8: 08048254     0 SECTION LOCAL  DEFAULT    8 
                 9: 0804825c     0 SECTION LOCAL  DEFAULT    9 
                10: 08048274     0 SECTION LOCAL  DEFAULT   10 
                11: 0804828c     0 SECTION LOCAL  DEFAULT   11 
                12: 080482d0     0 SECTION LOCAL  DEFAULT   12 
                13: 080484b4     0 SECTION LOCAL  DEFAULT   13 
                14: 080484d0     0 SECTION LOCAL  DEFAULT   14 
                15: 080484ec     0 SECTION LOCAL  DEFAULT   15 
                16: 080494f0     0 SECTION LOCAL  DEFAULT   16 
                17: 0804950c     0 SECTION LOCAL  DEFAULT   17 
                18: 080495d4     0 SECTION LOCAL  DEFAULT   18 
                19: 080495dc     0 SECTION LOCAL  DEFAULT   19 
                20: 080495e4     0 SECTION LOCAL  DEFAULT   20 
                21: 080495e8     0 SECTION LOCAL  DEFAULT   21 
                22: 08049604     0 SECTION LOCAL  DEFAULT   22 
                23: 00000000     0 SECTION LOCAL  DEFAULT   23 
                24: 00000000     0 SECTION LOCAL  DEFAULT   24 
                25: 00000000     0 SECTION LOCAL  DEFAULT   25 
                26: 00000000     0 SECTION LOCAL  DEFAULT   26 
                27: 080482f4     0 FUNC    LOCAL  DEFAULT   12 call_gmon_start
                28: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
                29: 080495d4     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_LIST__
                30: 080495dc     0 OBJECT  LOCAL  DEFAULT   19 __DTOR_LIST__
                31: 080484ec     0 OBJECT  LOCAL  DEFAULT   15 __EH_FRAME_BEGIN__
                32: 080495e4     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__
                33: 080494f8     0 OBJECT  LOCAL  DEFAULT   16 p.0
                34: 08049604     1 OBJECT  LOCAL  DEFAULT   22 completed.1
                35: 08048320     0 FUNC    LOCAL  DEFAULT   12 __do_global_dtors_aux
                36: 08048360     0 FUNC    LOCAL  DEFAULT   12 frame_dummy
                37: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
                38: 080495d8     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_END__
                39: 080495e0     0 OBJECT  LOCAL  DEFAULT   19 __DTOR_END__
                40: 080484ec     0 OBJECT  LOCAL  DEFAULT   15 __FRAME_END__
                41: 080495e4     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__
                42: 08048490     0 FUNC    LOCAL  DEFAULT   12 __do_global_ctors_aux
                43: 00000000     0 FILE    LOCAL  DEFAULT  ABS aaa.c
                44: 08049504     4 OBJECT  LOCAL  DEFAULT   16 c444   # static變量為L(zhǎng)OCAL綁定屬性(也即作用域) 已初始化靜態(tài)變量存放在.data
                45: 08049508     4 OBJECT  LOCAL  DEFAULT   16 c444.0 # 已初始化靜態(tài)變量存放在.data (多個(gè)源文件可以定義同名的靜態(tài)變量)
                46: 08049608     4 OBJECT  LOCAL  DEFAULT   22 c555   # 未初始化靜態(tài)變量存放在.bss
                47: 080494fc     4 OBJECT  GLOBAL DEFAULT   16 a111   # 全局變量為GLOBAL綁定屬性  已初始全局變量存放在.data
                48: 0804950c     0 OBJECT  GLOBAL DEFAULT   17 _DYNAMIC
                49: 080484d0     4 OBJECT  GLOBAL DEFAULT   14 _fp_hw
                50: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __fini_array_end
                51: 080494f4     0 OBJECT  GLOBAL HIDDEN   16 __dso_handle
                52: 08048440    66 FUNC    GLOBAL DEFAULT   12 __libc_csu_fini
                53: 08048274     0 FUNC    GLOBAL DEFAULT   10 _init
                54: 0804829c   427 FUNC    GLOBAL DEFAULT  UND malloc@@GLIBC_2.0    55: 080482d0     0 FUNC    GLOBAL DEFAULT   12 _start
                56: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __fini_array_start
                57: 080483f0    71 FUNC    GLOBAL DEFAULT   12 __libc_csu_init
                58: 08049500     4 OBJECT  GLOBAL DEFAULT   16 p111
                59: 08049604     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
                60: 0804838c    89 FUNC    GLOBAL DEFAULT   12 main
                61: 080482ac   251 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
                62: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __init_array_end
                63: 080494f0     0 NOTYPE  WEAK   DEFAULT   16 data_start
                64: 080484b4     0 FUNC    GLOBAL DEFAULT   13 _fini
                65: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __preinit_array_end
                66: 08049604     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
                67: 080495e8     0 OBJECT  GLOBAL DEFAULT   21 _GLOBAL_OFFSET_TABLE_
                68: 0804960c     0 NOTYPE  GLOBAL DEFAULT  ABS _end
                69: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __init_array_start
                70: 080484d4     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used
                71: 080494f0     0 NOTYPE  GLOBAL DEFAULT   16 __data_start
                72: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
                73: 080494f0     0 NOTYPE  GLOBAL HIDDEN  ABS __preinit_array_start
                74: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
                75: 080482bc    48 FUNC    GLOBAL DEFAULT  UND strcpy@@GLIBC_2.0
             
             
            文件./aaa加載進(jìn)內(nèi)存后,再看看變量的地址以及所在的區(qū):
            [test@redhat]# gdb ./aaa
            GNU gdb 6.1.1
            (gdb) disassemble main
            Dump of assembler code for function main:
            0x0804838c <main+0>:    push   %ebp
            0x0804838d <main+1>:    mov    %esp,%ebp
            0x0804838f <main+3>:    sub    $0x18,%esp
            0x08048392 <main+6>:    and    $0xfffffff0,%esp
            0x08048395 <main+9>:    mov    $0x0,%eax
            0x0804839a <main+14>:   sub    %eax,%esp
            # char s333[] = "abc";
            0x0804839c <main+16>:   mov    0x80484df,%eax            # 0x80484df處為"abc",位于.rodata
            0x080483a1 <main+21>:   mov    %eax,0xfffffff8(%ebp)     # 0xfffffff8(%ebp) 為局部變量 char s333[]
            # char *p333 = "123456";
            0x080483a4 <main+24>:   movl   $0x80484e3,0xfffffff0(%ebp)  # 0x80484e3處為"123456/0",位于.rodata; 0xfffffff0(%ebp) 為局部變量 char *p333
            # p111 = (char *)malloc(10);
            0x080483ab <main+31>:   sub    $0xc,%esp
            0x080483ae <main+34>:   push   $0xa          # 0xa=10 ; push $0xa后,此時(shí)堆棧esp值又減去4字節(jié),相當(dāng)于sub $0x10,%esp
            0x080483b0 <main+36>:   call   0x804829c <malloc>
            0x080483b5 <main+41>:   add    $0x10,%esp
            0x080483b8 <main+44>:   mov    %eax,0x8049500  # 0x8049500 為全局變量p111,位于.data
            # p222 = (char *)malloc(20);
            0x080483bd <main+49>:   sub    $0xc,%esp
            0x080483c0 <main+52>:   push   $0x14        # 0x14=20 ; push $0xa后,此時(shí)堆棧esp值又減去4字節(jié),相當(dāng)于sub $0x10,%esp
            0x080483c2 <main+54>:   call   0x804829c <malloc>
            0x080483c7 <main+59>:   add    $0x10,%esp
            0x080483ca <main+62>:   mov    %eax,0xfffffff4(%ebp)  # 0xfffffff4(%ebp) 為局部變量p222
            # strcpy(p111, "123456");
            0x080483cd <main+65>:   sub    $0x8,%esp
            0x080483d0 <main+68>:   push   $0x80484e3    # 0x80484e3處內(nèi)容為"123456/0",位于.rodata; 
            0x080483d5 <main+73>:   pushl  0x8049500     # 0x8049500 為全局變量p111,位于.data
            0x080483db <main+79>:   call   0x80482bc <strcpy>
            0x080483e0 <main+84>:   add    $0x10,%esp
            0x080483e3 <main+87>:   leave  
            0x080483e4 <main+88>:   ret    
            0x080483e5 <main+89>:   nop    
            0x080483e6 <main+90>:   nop    
            0x080483e7 <main+91>:   nop    
            0x080483e8 <main+92>:   nop    
            0x080483e9 <main+93>:   nop    
            0x080483ea <main+94>:   nop    
            0x080483eb <main+95>:   nop    
            0x080483ec <main+96>:   nop    
            0x080483ed <main+97>:   nop    
            0x080483ee <main+98>:   nop    
            0x080483ef <main+99>:   nop    
            End of assembler dump.
            (gdb) q
            [test@redhat]#
             

            posted on 2009-10-30 10:55 葉子 閱讀(2452) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C\C++

            久久国产高清一区二区三区| 99国产欧美精品久久久蜜芽| 欧美麻豆久久久久久中文| 久久无码一区二区三区少妇| 久久久久久久综合狠狠综合| 一本色道久久88—综合亚洲精品| 麻豆一区二区99久久久久| 国产欧美一区二区久久| 亚洲精品国产第一综合99久久| 久久综合88熟人妻| 婷婷久久精品国产| 国产精品久久久久影院色| 久久久久久亚洲精品影院| 777久久精品一区二区三区无码| 精品久久久久久无码不卡| 久久久久综合网久久| 嫩草伊人久久精品少妇AV| 久久精品无码专区免费| 99国产精品久久久久久久成人热| 国产一区二区久久久| 久久久精品国产Sm最大网站| 久久天堂电影网| 久久精品毛片免费观看| 亚洲精品无码久久久久sm| 久久99热这里只频精品6| 国内精品久久久久久久久电影网| 久久国产精品一国产精品金尊| 中文字幕久久精品| 久久天天躁狠狠躁夜夜2020老熟妇| 国产Av激情久久无码天堂| 久久亚洲美女精品国产精品| 国产精品99久久久精品无码| 久久久久亚洲AV综合波多野结衣| 国产精品综合久久第一页| 久久久青草青青亚洲国产免观| 久久se精品一区精品二区| 97久久久久人妻精品专区| 久久ZYZ资源站无码中文动漫| 色综合久久久久无码专区 | 国产精品久久久久久久久久免费| 韩国无遮挡三级久久|