[英]What exactly happens when you dereference a static variable in C?
所以說我有這個代碼
int my_static_int = 4;
func(&my_static_int);
顯然,我向函數傳遞了指向my_static_int的指針。 但是,編譯代碼時會發生什么? 我考慮過的大道:
1)當您聲明一個非指針變量時,C會自動創建其指針,並在內部做一些類似typedefs my_static_int的*( internal_reference )
無論如何,我希望我的問題足夠描述性
指針只是一個術語,可以幫助我們人類了解正在發生的事情。
&運算符與變量一起使用時,僅表示地址。 在運行時沒有創建“指針”,您只是將變量的地址傳遞給函數。
如果你有:
int x = 3;
int* p = &x;
那么p是一個保存內存地址的變量。 在該內存地址內是一個int。
如果您真的想知道代碼的幕后外觀,則必須讓編譯器生成匯編代碼( gcc
可以使用-S
選項執行此操作)。
當真正了解C和指針的最深層次時,您會意識到,它只是傳入的變量的地址,而不是變量的值。 無需創建額外的內存來容納指針,因為指針直接從代碼移到了堆棧(地址可能是在鏈接時或加載時設置的,而不是在運行時設置的)。
因為編譯后的代碼已經知道類型以及如何操作它,所以也不需要內部類型創建。
請記住,這是特定於實現的,請考慮以下代碼:
int my_static_int = 4;
static void func (int *x) {
*x = *x + 7;
}
int main (void) {
func(&my_static_int);
return 0;
}
使用gcc -S
進行編譯以獲取匯編程序時,將產生以下結果:
.file "qq.c"
.globl _my_static_int
.data
.align 4
_my_static_int:
.long 4
.text
.def _func; .scl 3; .type 32; .endef
_func:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl 8(%ebp), %edx
movl (%edx), %edx
addl $7, %edx
movl %edx, (%eax)
popl %ebp
ret
.def ___main; .scl 2; .type 32; .endef
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
movl $_my_static_int, (%esp)
call _func
movl $0, %eax
leave
ret
重要的是這些部分:
movl $_my_static_int, (%esp) ; load address of variable onto stack.
call _func ; call the function.
:
movl 8(%ebp), %eax ; get passed parameter (the address of the var) into eax
movl 8(%ebp), %edx ; and also into edx.
movl (%edx), %edx ; get the value from the address (dereference).
addl $7, %edx ; add 7 to it.
movl %edx, (%eax) ; and put it back into the same address.
因此, 地址被傳遞,並用於獲取變量。
編譯代碼后,函數func
接收my_static_int
變量的地址作為參數。 沒有其他的。
聲明非指針變量時,無需創建任何隱式指針。 從您的問題尚不清楚您是如何想到這個奇怪的想法的。
為什么不看匯編輸出? 您可以使用-S
選項使用gcc
進行此操作,也可以對所得的目標文件或可執行文件使用objdump -d
命令(如果您的系統使用GNU工具鏈)。
簡單的答案是,目標代碼生成對分配了my_static_int
的符號的引用(通常位於目標模塊的靜態數據段中)。
因此,變量的地址在加載時解析(當為其分配了實際的物理地址時),並且加載程序將對變量的引用固定,並用其地址填充。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.