我正在學習 C 語言,特別是指標,我有這個小問題。
如何將兩個資料保存在 C 的同一記憶體位置?看我的代碼:
#include <stdio.h>
int main()
{
const int y = 2;
int *const ptr_y = &y;
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", &y);
printf("%p\n", ptr_y);
return (0);
}
輸出:
2
4
0x7ffeeb501788
0x7ffeeb501788
我期望的輸出:
4
4
0x7ffeeb501788
0x7ffeeb501788
我想知道這段代碼在內部是如何作業的。
重要提示:我知道常量指標未正確宣告(const int *ptr_y)。
uj5u.com熱心網友回復:
首先,int *const ptr_y = &y;它不是有效的 C,因此,如果您的編譯器盡管有此代碼但仍生成了可執行檔案,那么對其行為的所有賭注都將被取消。如果您沒有收到來自編譯器的訊息,則意味著您的編譯器配置是非標準的。請參閱為學習 C 的初學者推薦哪些編譯器選項?
嚴格來說printf("%p\n", &y);也應該投到(const void*)&y。
Cconst int y = 2;標準未指定存盤值 2 的位置。它可以在暫存器中,在堆疊上,在標有“只讀”(.rodata或類似)的讀/寫存盤器中,或者在嵌入式系統的情況下,它可以存盤在真正的只讀存盤器中,如閃存。
如果您對該記憶體位置進行寫訪問,則行為不是由 C 標準定義的。未定義的行為= 任何事情都可能發生,包括:
- 它可以更新記憶體,下次你讀回
4. - 它可以更新記憶體,但編譯器優化器不會生成代碼來讀回它,所以你仍然得到
2. - 編譯器可以忽略為寫入嘗試生成代碼。
- 它可能是真正的只讀存盤器,因此當您嘗試寫入它時,什么也沒有發生。
- 它可能是真正的只讀存盤器并受到保護,因此寫入嘗試會導致硬體例外或類似情況。
總的來說,當您呼叫未定義的行為時,分析究竟發生了什么(癥狀)并沒有太大意義。重要的是了解為什么代碼包含未定義的行為(根本原因)。
uj5u.com熱心網友回復:
該代碼呼叫未定義的行為,因為您無法更改const變數的內容,因此輸出沒有意義,它可以是上面鏈接的未定義行為的定義中的任何內容。
您沒有將資料保存在兩個不同的位置,而是相同的位置。
y存盤在某個(記憶體)位置,該位置有一個地址,ptr_y是一個指標,它包含相同的記憶體地址,因為您使用address-ofoperator分配了它&:
int *const ptr_y = &y;
上面的賦值丟棄了const限定符,因此,編譯器允許您嘗試更改ywith的值*ptr_y = 4,這仍然無效,但由于錯誤的賦值,它成為可能。如果您使用過,您應該始終尊重const指標中的限定詞:
const int y = 2;
const int* ptr_y = &y;
編譯器不會讓你這樣做:
*ptr_y = 4;
錯誤:分配只讀位置'* ptr_y'
使用正確的代碼,通過取消參考ptr_yusing*運算子,您正在訪問存盤的地址,ptr_y其中偶然是 的地址y,因此它是相同的記憶體地址,您只是以兩種不同的方式訪問它:
int y = 2; // non const
int *const ptr_y = &y; // constant pointer is allowed
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", (void*)&y); // %p specifier expects void*
printf("%p\n", (void*)ptr_y);
4
4
0x7ffd0f9aee34
0x7ffd0f9aee34
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/473145.html
標籤:C
