如果我們有
int a = 123
int b = 123
我們最終會為整數分配兩個不同的123記憶體塊,還是最終只分配一個記憶體塊123?
關于什么
int a = 123
int b = a
這會改變答案嗎?
uj5u.com熱心網友回復:
C 和 C 程式具有雙重性質。程式的含義是使用帶有抽象計算機的理論模型來描述的,該計算機按照源代碼的描述逐字執行程式。在這個模型中,每個物件都具有與其他物件不同的記憶體,因為根據定義,物件是保留記憶體,與型別相關聯。(請注意,源代碼中的字串文字可能會重疊,指的是一個公共陣列。)
但是,編譯器不需要生成按字面意思執行此含義的匯編代碼。它可以生成與原始源代碼具有相同可觀察行為的任何程式。可觀察的行為包括程式寫入檔案的輸出、輸入/輸出互動以及對易失性物件的訪問。在可觀察到的行為之間,編譯器可以優化程式,包括消除不必要的記憶體使用。
每當您定義一個物件時,如果編譯器能夠在不使用此類記憶體的情況下使您的程式作業,編譯器可能根本不會為它保留記憶體。例如,在:
int main(void)
{
int a = 123;
int b;
scanf("%d", &b);
printf("%d\n", a b);
}
編譯器很可能通過加載常量 123 作為指令的立即操作來執行計算,而不為它保留單獨的記憶體。
如果編譯器確實需要記憶體,可能是因為它沒有足夠的處理器暫存器來將它正在使用的所有內容保存在暫存器中,那么它可能只保留一個常量副本,該常量用于初始化兩個永遠不會更改的物件,其地址不采取。
如果您通過地址將物件傳遞給其他例程或賦予它們不同的值,則編譯器更有可能根據情況為它們保留單獨的記憶體。
uj5u.com熱心網友回復:
Eric 的回答已經是很好的回答了,我會用一個簡單的實際案例來補充,取下面的代碼:
#include <stdio.h>
int main() {
int a = 123;
int b = 123;
printf("%d", a);
printf("%d", b);
}
如果您使用 gcc 11.2 x86-64 C 編譯器編譯此代碼,則會生成以下程式集:
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 123
mov DWORD PTR [rbp-8], 123
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, DWORD PTR [rbp-8]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
如您所見,為 2 個變數提供了存盤空間。
現在,如果我使用優化-O標志,則會生成以下程式集:
.LC0:
.string "%d"
main:
sub rsp, 8
mov esi, 123
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov esi, 123
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
add rsp, 8
ret
正如您所看到的,編譯器只使用123文字,因為沒有對這些變數進行任何更改,它們可以被視為常量值。
所以答案是視情況而定,我們甚至可能最終沒有存盤任何變數。
ato的賦值b本身沒有任何改變。
uj5u.com熱心網友回復:
我們最終會分配兩個不同的記憶體塊嗎
就抽象機而言:是的,變數具有重疊的存盤持續時間,因此它們必須具有不同的記憶體地址。
就語言實作而言:這取決于。如果不需要,甚至可能根本不使用記憶體。
這會改變答案嗎?
不。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/407555.html
標籤:
