全局变量和局部变量在内存里的区别.docx
- 文档编号:15856849
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:13
- 大小:19.50KB
全局变量和局部变量在内存里的区别.docx
《全局变量和局部变量在内存里的区别.docx》由会员分享,可在线阅读,更多相关《全局变量和局部变量在内存里的区别.docx(13页珍藏版)》请在冰点文库上搜索。
全局变量和局部变量在内存里的区别
全局变量和局部变量在内存里的区别
全局变量和局部变量在内存里的区别收藏
一、预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(.data),未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss)。
-程序结束后由系统释放。
4、文字常量区—常量字符串就是放在这里的(.rodata)。
程序结束后由系统释放。
5、程序代码区—存放函数体的二进制代码(.text)。
二、例子程序
这是一个前辈写的,非常详细
//main.cpp
inta=0; //全局初始化区
char*p1; //全局未初始化区
main()
{
intb; //栈区
chars[]="abc";//栈区
char*p2; //栈区
char*p3="123456"; //"123456\0"在常量区,p3在栈区
staticintc=0; //全局(静态)初始化区
p1=(char*)malloc(10);
p2=(char*)malloc(20);//分配得来的10和20字节的区域就在堆区
strcpy(p1,"123456"); //"123456\0"放在常量区,编译器可能会将它
//与p3所指向的"123456"优化成一个地方。
}
==============================================================
static全局变量与普通的全局变量有什么区别?
static局部变量和普通局部变量有什么区别?
static函数与普通函数有什么区别?
static全局变量与普通的全局变量有什么区别?
static局部变量和普通局部变量有什么区别?
static函数与普通函数有什么区别?
答:
1) 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。
全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。
这两者在存储方式上并无不同。
这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
2) 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。
把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。
3)static函数与普通函数作用域不同,仅在本文件。
只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。
对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
综上所述:
static全局变量与普通的全局变量有什么区别:
static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:
static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
==============================================================
一个C语言变量分配的实际例子:
我们来看看在可执行文件中,变量们会被分配在哪些区里.这里以可执行文件为例子,可执行文件有固定的内存加载地址,符号(函数/变量的名字)将来在内存里的地址连接器是可以提前确定的。
源程序编译连接的结果是形成1堆汇编指令代码,大致分为.text.data.bss等几个节区(section)。
对于.exe文件和.so文件,全局和静态变量都放在.data或.bss段(gas把源文件从头到尾扫描1遍,才知道一个变量的全部情况:
是否定义;类型;是否初始化。
然后把初始化的变量在.data段里分配位置和空间,把没初始化的变量在.bss段里分配位置和空间,没定义的变量分配在.undef段)。
汇编指令代码里全局变量表现为一个内存地址(全局变量在目标文件里是一个偏移值,加载进内存里是一个内存地址)。
临时变量在汇编代码里变成ebp/esp+n,表现为一个堆栈地址,化为程序正文(.text)的一部分。
有些变量的最终内存地址在加载进内存之前还不能确定,需要加载进内存才可以计算出来.
全局变量作用域是跨越多个源程序的。
因此全局变量不能重名。
静态变量作用域是位于单个源程序内。
多个源程序可以有同名的全局静态变量。
本例中,为了区分多个同名的静态变量,gcc用c444和c444.0来加以区别。
[test@redhat]#moreaaa.c
#include
inta111=0; #全局变量已初始化
char*p111="654321"; #全局指针变量已经初始化
staticintc444=9; #静态全局变量已经初始化
staticintc555; #静态全局变量未初始化
main()
{
intb222; #局部变量
chars333[]="abc"; #局部变量
char*p222; #局部变量
char*p333="123456"; #局部变量
staticintc444=0; #已初始化静态局部变量,与前面静态全局变量重名
p111=(char*)malloc(10);
p222=(char*)malloc(20);
strcpy(p111,"123456");
}
[test@redhat]#gcc-oaaa./aaa.c
[test@redhat]#readelf-a./aaa
ELFHeader:
Magic:
7f454c46010101000000000000000000
Class:
ELF32
Data:
2'scomplement,littleendian
Version:
1(current)
OS/ABI:
UNIX-SystemV
ABIVersion:
0
Type:
EXEC(Executablefile)
Machine:
Intel80386
Version:
0x1
Entrypointaddress:
0x80482d0
Startofprogramheaders:
52(bytesintofile)
Startofsectionheaders:
2040(bytesintofile)
Flags:
0x0
Sizeofthisheader:
52(bytes)
Sizeofprogramheaders:
32(bytes)
Numberofprogramheaders:
7
Sizeofsectionheaders:
40(bytes)
Numberofsectionheaders:
27
Sectionheaderstringtableindex:
24
SectionHeaders:
Addr是文件加载进内存时,每个section在内存中的虚拟地址
[Nr]Name Type Addr Off Size ESFlgLkInfAl
[0] NULL 0000000000000000000000 0 0 0
[1].interp PROGBITS 0804811400011400001300 A 0 0 1
[2].note.ABI-tag NOTE 0804812800012800002000 A 0 0 4
[3].hash HASH 0804814800014800002c04 A 4 0 4
[4].dynsym DYNSYM 0804817400017400006010 A 5 1 4
[5].dynstr STRTAB 080481d40001d400005300 A 0 0 1
[6].gnu.version VERSYM 0804822800022800000c02 A 4 0 2
[7].gnu.version_r VERNEED 0804823400023400002000 A 5 1 4
[8].rel.dyn REL 0804825400025400000808 A 4 0 4
[9].rel.plt REL 0804825c00025c00001808 A 4 b 4
[10].init PROGBITS 0804827400027400001700 AX 0 0 4
[11].plt PROGBITS 0804828c00028c00004004 AX 0 0 4
[12].text PROGBITS 080482d00002d00001e400 AX 0 016
[13].fini PROGBITS 080484b40004b400001b00 AX 0 0 4
[14].rodata PROGBITS 080484d00004d000001a00 A 0 0 4
[15].eh_frame PROGBITS 080484ec0004ec00000400 A 0 0 4
[16].data PROGBITS 080494f00004f000001c00 WA 0 0 4
[17].dynamic DYNAMIC 0804950c00050c0000c808 WA 5 0 4
[18].ctors PROGBITS 080495d40005d400000800 WA 0 0 4
[19].dtors PROGBITS 080495dc0005dc00000800 WA 0 0 4
[20].jcr PROGBITS 080495e40005e400000400 WA 0 0 4
[21].got PROGBITS 080495e80005e800001c04 WA 0 0 4
[22].bss NOBITS 0804960400060400000800 WA 0 0 4
[23].comment PROGBITS 0000000000060400012600 0 0 1
[24].shstrtab STRTAB 0000000000072a0000ce00 0 0 1
[25].symtab SYMTAB 00000000000c300004c010 26 2f 4
[26].strtab STRTAB 000000000010f000027500 0 0 1
ProgramHeaders:
Type Offset VirtAddr PhysAddr FileSizMemSiz FlgAlign
PHDR 0x0000340x080480340x080480340x000e00x000e0RE0x4
INTERP 0x0001140x080481140x080481140x000130x00013R 0x1
[Requestingprograminterpreter:
/lib/ld-linux.so.2]
LOAD 0x0000000x080480000x080480000x004f00x004f0RE0x1000
LOAD 0x0004f00x080494f00x080494f00x001140x0011cRW 0x1000
DYNAMIC 0x00050c0x0804950c0x0804950c0x000c80x000c8RW 0x4
NOTE 0x0001280x080481280x080481280x000200x00020R 0x4
STACK 0x0000000x000000000x000000000x000000x00000RW 0x4
Symboltable'.symtab'contains76entries:
对于.exe文件,符号的Value是将来加载进内存中的真实地址;对于.so文件Value需要重定位.
Num:
Value SizeType Bind Vis NdxName
0:
00000000 0NOTYPE LOCAL DEFAULT UND
1:
08048114 0SECTIONLOCAL DEFAULT 1
2:
08048128 0SECTIONLOCAL DEFAULT 2
3:
08048148 0SECTIONLOCAL DEFAULT 3
4:
08048174 0SECTIONLOCAL DEFAULT 4
5:
080481d4 0SECTIONLOCAL DEFAULT 5
6:
08048228 0SECTIONLOCAL DEFAULT 6
7:
08048234 0SECTIONLOCAL DEFAULT 7
8:
08048254 0SECTIONLOCAL DEFAULT 8
9:
0804825c 0SECTIONLOCAL DEFAULT 9
10:
08048274 0SECTIONLOCAL DEFAULT 10
11:
0804828c 0SECTIONLOCAL DEFAULT 11
12:
080482d0 0SECTIONLOCAL DEFAULT 12
13:
080484b4 0SECTIONLOCAL DEFAULT 13
14:
080484d0 0SECTIONLOCAL DEFAULT 14
15:
080484ec 0SECTIONLOCAL DEFAULT 15
16:
080494f0 0SECTIONLOCAL DEFAULT 16
17:
0804950c 0SECTIONLOCAL DEFAULT 17
18:
080495d4 0SECTIONLOCAL DEFAULT 18
19:
080495dc 0SECTIONLOCAL DEFAULT 19
20:
080495e4 0SECTIONLOCAL DEFAULT 20
21:
080495e8 0SECTIONLOCAL DEFAULT 21
22:
08049604 0SECTIONLOCAL DEFAULT 22
23:
00000000 0SECTIONLOCAL DEFAULT 23
24:
00000000 0SECTIONLOCAL DEFAULT 24
25:
00000000 0SECTIONLOCAL DEFAULT 25
26:
00000000 0SECTIONLOCAL DEFAULT 26
27:
080482f4 0FUNC LOCAL DEFAULT 12call_gmon_start
28:
00000000 0FILE LOCAL DEFAULT ABScrtstuff.c
29:
080495d4 0OBJECT LOCAL DEFAULT 18__CTOR_LIST__
30:
080495dc 0OBJECT LOCAL DEFAULT 19__DTOR_LIST__
31:
080484ec 0OBJECT LOCAL DEFAULT 15__EH_FRAME_BEGIN__
32:
080495e4 0OBJECT LOCAL DEFAULT 20__JCR_LIST__
33:
080494f8 0OBJECT LOCAL DEFAULT 16p.0
34:
08049604 1OBJECT LOCAL DEFAULT 22completed.1
35:
08048320 0FUNC LOCAL DEFAULT 12__do_global_dtors_aux
36:
08048360 0FUNC LOCAL DEFAULT 12frame_dummy
37:
00000000 0FILE LOCAL DEFAULT ABScrtstuff.c
38:
080495d8 0OBJECT LOCAL DEFAULT 18__CTOR_END__
39:
080495e0 0OBJECT LOCAL DEFAULT 19__DTOR_END__
40:
080484ec 0OBJECT LOCAL DEFAULT 15__FRAME_END__
41:
080495e4 0OBJECT LOCAL DEFAULT 20__JCR_END__
42:
08048490 0FUNC LOCAL DEFAULT 12__do_global_ctors_aux
43:
00000000 0FILE LOCAL DEFAULT ABSaaa.c
44:
08049504 4OBJECT LOCAL DEFAULT 16c444 #static变量为LOCAL绑定属性(也即作用域)已初始化静态变量存放在.data
45:
08049508 4OBJECT LOCAL DEFAULT 16c444.0 #已初始化静态变量存放在.data(多个源文件可以定义同名的静态变量)
46:
08049608 4OBJECT LOCAL DEFAULT 22c555 #未初始化静态变量存放在.bss
47:
080494fc 4OBJECT GLOBALDEFAULT 16a111 #全局变量为GLOBAL绑定属性 已初始全局变量存放在.data
48:
0804950c 0OBJECT GLOBALDEFAULT 17_DYNAMIC
49:
080484d0 4OBJECT GLOBALDEFAULT 14_fp_hw
50:
080494f0 0NOTYPE GLOBALHIDDEN ABS__fini_array_end
51:
080494f4 0OBJECT GLOBALHIDDEN 16__dso_handle
52:
08048440 66FUNC GL
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 全局变量 局部 变量 在内 区别