[英]How to get the actual address of a pointer in C?
背景:
我正在C中編寫一個單級緩存模擬器來完成作業,我已經獲得了必須使用的代碼。 在我們對緩存的討論中,我們被告知小緩存可以容納大地址的方式是將大地址分成緩存中的位置和識別標記。 也就是說,如果你有一個8槽緩存但想要存儲地址大於8的東西,你可以取3(因為2 ^ 3 = 8)最右邊的位並將數據放在那個位置; 因此,如果您有地址22,例如二進制10110,您將獲取那些最右邊的位110,即十進制5,並將其放入緩存的插槽5中。 您還可以在此位置存儲標記,即剩余的位10。
一個函數cache_load接受一個參數和整數指針。 所以有效的是,我正在給這個int * addr這是一個實際的地址,並指向一些值。 為了將此值存儲在緩存中,我需要拆分addr。 但是,當我嘗試直接使用指針時,編譯器不喜歡。 所以,例如,我試圖通過這樣做來獲得這個位置:
npos=addr%num_slots
編譯器生氣並給我錯誤。 我嘗試轉換為int,但這實際上得到了指針指向的值,而不是數字地址本身。 任何幫助表示贊賞,謝謝!
[編輯]
int load(int * addr) {
int value = (use_memory ? (*addr) : 0);
intptr_t taddr=(intptr_t) addr;
int npos=taddr % blocks;
int ntag=taddr / blocks;
printf("addr is %p, taddr is %p, npos is %d and ntag is %d\n",addr,taddr,npos,ntag);
當傳入addr時,它的實際地址是58,它指向值88.我從該printf得到的輸出是:
addr是58,taddr是58,npos是0,ntag是11
所以似乎taddr得到58(當用%p打印時,在打印%d時仍然顯示88),但是npos和ntag顯示為0和11(好像數學運算用88運行)而不是2和我一樣。
代碼使用如下:
void load_words (int n, int words[]) {
int i;
for (i=0; i<n; i++) {
load( (int *) (words[i] * 4));
cache_print();
}
}
你應該使用類似的東西
int *pointer;
intptr_t address=(intptr_t) pointer;
這主要只是對@ Andrew的帖子的修正
所以你的功能應該成為
(哎呀忘了這是家庭作業。我會在一段時間內回復這個問題。不能直接給你答案:))
C99標准表示從指針類型到整數類型的轉換(反之亦然)是實現定義的行為(6.3.2.3.5和6.3.2.3.6),除非使用<stdint.h>
定義的intptr_t
或uintptr_t
但是7.18.1.4說這兩種類型不是強制性的,並且實現不需要提供它們。
int *pointer;
uint32_t address = (uint32_t) pointer;
當然,除了你不能保證int *適合uint32_t,所以你需要為你的平台選擇正確的類型。
十進制88是0x58(十六進制58)。 將%p說明符與printf一起使用時,將打印出十六進制表示。 所以addr和taddr都是十進制88,你的計算是正確的。
這里還沒有提到一個重要的事情。 當您使用%p說明符打印指針時,您應該轉換參數:
printf("addr is %p\n", (void *)addr);
%p期望指向void,而printf的說明符/參數不匹配是未定義的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.