簡體   English   中英

C ++文字常量存儲在內存中的哪里?

[英]Where the C++ literal-constant storage in memory?

C ++文字常量存儲在內存中的哪里? 堆還是堆?

int *p = &2

是錯的。 我想知道為什么嗎? 謝謝

-------------------------------------------------

我的問題是“內存中的C ++文字常量存儲在哪里”,“ int *p = &2

是錯的”,不是我的問題。

詳細信息取決於機器,但是假設機器和操作系統是最普通的……每個可執行文件都包含多個“段”-CODE,BSS,DATA等。

CODE包含所有可執行的操作碼。 實際上,它通常被命名為TEXT,是因為它在幾十年前的人們中是有道理的。 通常,它是只讀的。

BSS是未初始化的數據-實際上它不需要存在於可執行文件中,而是在程序開始運行時由操作系統的加載程序分配的。

DATA保存文字常量-int8,int16,int32等以及浮點數,字符串文字以及編譯器和鏈接器關心產生的任何奇怪的東西。 這就是您要問的問題。 但是,它僅保留定義為用作變量的常量,如

const long x = 2;

但不太可能保留源代碼中使用的文字常量,但不能與變量緊密關聯。 編譯器直接處理一個單獨的“ 2”。 例如在C中

print("%d", 2);

會導致編譯器生成對print()的子例程調用,編寫操作碼以將指針推向字符串文字“%d”和值2,這兩個指針在64位計算機上都是64位整數(您不是那些仍在使用32位硬件的落后者之一,是嗎?:),然后是操作碼,可跳至位於(“ print”子例程的標識符)處的子例程。

“%d”文字輸入DATA。 2個沒有; 它內置在將整數填充到堆棧中的操作碼中。 實際上,這可能是“立即加載寄存器RAX”,后跟值2,然后是“推送寄存器RAX”,或者可能只有一個操作碼就可以完成這項工作。 因此,在最終的可執行文件中,將在CODE(aka TEXT)段中找到2。

通常不可能創建指向該值或任何操作碼的指針。 就像C這樣的高級語言而言,這根本沒有意義(當您談論操作碼和段時,C是“高級”。)“&2”只能是一個錯誤。

現在,擁有操作碼的指針並不是完全不可能的。 每當您在C中定義一個函數或在C ++中定義一個對象方法,構造函數或析構函數時,該函數的名稱都可以被視為指向從該函數編譯的機器代碼的第一個操作碼的指針。 例如,不帶括號的print()是指向函數的指針。 也許如果您的示例代碼在函數中並且您猜到了正確的偏移量,則可以使用指針算法指向操作碼中嵌套的“立即”值2,但這對於任何當代的CPU來說都不容易,當然不適合初學者。

讓我引用C ++ 03 Standard的相關條款。 5.3.1 / 2

一元&運算符的結果是指向其操作數的指針。 操作數應為左值。

整數文字是一個右值(但是,我在C ++ 03 Standard中沒有找到直接引號,但是C ++ 11在3.10 / 1中將其作為附帶說明)。 因此,不可能采用整數文字的地址。

關於存儲2的確切位置呢,取決於使用情況。 它可能是機器指令的一部分,或者可能被優化掉了,例如j=i*2可能變成j=i+i 您不應該依賴它。

您有兩個問題:

文字常量存儲在哪里? 除了字符串文字(它們是實際的對象)外,幾乎在實現所需的任何地方。 它通常取決於您對它們的處理方式,但是在許多體系結構上,整數常量(通常是一些特殊的浮點常量,例如0.0 )最終將作為機器指令的一部分。 如果不可能,則通常將它們與代碼放在同一邏輯段中。

至於為什么取一個右值的地址是非法的,主要原因是因為該標准是這樣說的。 從歷史上看,它是被禁止的,因為這樣的常量在內存中通常永遠不會作為單獨的對象存在,因此沒有地址。 如今……人們可以想象出其他解決方案:如果您獲得了地址,編譯器足夠聰明,可以將它們存儲在內存中;否則,它就可以了。 類類型的右值確實有一個內存地址。 這些規則在某種程度上是任意的(並且無論它們是什么,都將是任意的)—希望任何允許采用文字地址的規則都將使其類型為int const* ,而不是int*

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM