第七章 變量的位置

本文介紹C/C++中變量存儲的位置:包括 全局變量,靜態局部變量,堆變量

#include<stdio.h>
int g_variable1 = 12345;
int g_variable2 = 45678;

int main()
{
	int one =1,two =2;
	scanf("%d,%d",&one,&two);
	printf("%d,%d\n",one,two);
	scanf("%d,%d",&g_variable1,&g_variable2);
	printf("%d,%d\n",g_variable1,g_variable2);
	return 0;
}

編譯後的彙編代碼

_DATA	SEGMENT
_g_variable1 DD	03039H
_g_variable2 DD	0b26eH
_DATA	ENDS

由上一部分可知 全局變量在data段中


CONST	SEGMENT
??_C@_05BBIB@?$CFd?0?$CFd?$AA@ DB '%d,%d', 00H		; `string'
CONST	ENDS
;	COMDAT ??_C@_06JDIH@?$CFd?0?$CFd?6?$AA@
CONST	SEGMENT
??_C@_06JDIH@?$CFd?0?$CFd?6?$AA@ DB '%d,%d', 0aH, 00H	; `string'
CONST	ENDS
;	COMDAT _main
_TEXT	SEGMENT
_one$ = -4
_two$ = -8
_main	PROC NEAR					; COMDAT

; 6    : {

	push	ebp
	mov	ebp, esp
	sub	esp, 72					; 00000048H
	push	ebx
	push	esi
	push	edi
	lea	edi, DWORD PTR [ebp-72]
	mov	ecx, 18					; 00000012H
	mov	eax, -858993460				; ccccccccH
	rep stosd

; 7    : 	int one =1,two =2;

	mov	DWORD PTR _one$[ebp], 1         ;這裏存one
	mov	DWORD PTR _two$[ebp], 2         ;這裏存two
; 8    : 	scanf("%d,%d",&one,&two);

	lea	eax, DWORD PTR _two$[ebp]
	push	eax
	lea	ecx, DWORD PTR _one$[ebp]
	push	ecx
	push	OFFSET FLAT:??_C@_05BBIB@?$CFd?0?$CFd?$AA@ ; `string'
	call	_scanf
	add	esp, 12					; 0000000cH

; 9    : 	printf("%d,%d\n",one,two);

	mov	edx, DWORD PTR _two$[ebp]
	push	edx
	mov	eax, DWORD PTR _one$[ebp]
	push	eax
	push	OFFSET FLAT:??_C@_06JDIH@?$CFd?0?$CFd?6?$AA@ ; `string'
	call	_printf
	add	esp, 12					; 0000000cH

; 10   : 	scanf("%d,%d",&g_variable1,&g_variable2);

	push	OFFSET FLAT:_g_variable2
	push	OFFSET FLAT:_g_variable1
	push	OFFSET FLAT:??_C@_05BBIB@?$CFd?0?$CFd?$AA@ ; `string'
	call	_scanf
	add	esp, 12					; 0000000cH

; 11   : 	printf("%d,%d\n",g_variable1,g_variable2);

	mov	ecx, DWORD PTR _g_variable2
	push	ecx
	mov	edx, DWORD PTR _g_variable1
	push	edx
	push	OFFSET FLAT:??_C@_06JDIH@?$CFd?0?$CFd?6?$AA@ ; `string'
	call	_printf
	add	esp, 12					; 0000000cH

由上代碼發現:全局變量在數據區,生命週期與模塊一致,使用立即數訪問;

局部變量在棧區,使用ebp或esp訪問(優化後會使用esp訪問)


問題:關於局部靜態變量:存儲位置?初始化方式?

C語言中是不允許對局部靜態變量用非常量賦初值的,C++中允許使用


#include<iostream>
void func(int a)
{
        static int b = a;
}
int main()
{
        int a;
        func(a);
        return 0;
}


以下是func中對應的彙編實現


; 4    :         static int b = a;

	xor	eax, eax
	mov	al, BYTE PTR _?$S25@?1??func@@YAXH@Z@4EA
	and	eax, 1	 //eax 與1 做位與運算,
	test	eax, eax
	jne	SHORT $L7353	//測試,不等跳轉
	mov	cl, BYTE PTR _?$S25@?1??func@@YAXH@Z@4EA
	or	cl, 1
	mov	BYTE PTR _?$S25@?1??func@@YAXH@Z@4EA, cl   //將 那個地址賦1
	mov	edx, DWORD PTR _a$[ebp]			
	mov	DWORD PTR _?b@?1??func@@YAXH@Z@4HA, edx    //對 b 賦值
$L7353:
; 5    : }




由上可知,比較的標誌位是用來讓static變量初始化一次的,如果該位爲1 ,則說明已經初始化,不需要再初始化。


關於堆變量:數據在new或malloc時,返回數據在堆中的地址,具體讀者請自行實驗。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章