[英]What is the difference between pointer's address and the int value converted from pointer
我認為ptr的地址和a的地址彼此相同。 而且我還認為ptr的地址與從指針轉換的int值相同。
但是控制台的結果拒絕了我,這是什么原因? 我如何理解結果。
#include <stdio.h>
int main() {
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *) ((int) a);
printf("a's address: %p \n", a);
printf("ptr's address: %p \n", ptr);
printf("ptr's int value: %x", (int)ptr);
return 0;
}
控制台的結果是
a's address: 0x7ffee8d30600
ptr's address: 0xffffffffe8d30600
ptr's int value: e8d30600
PS
我已經編輯了標題,並且原始的模棱兩可的標題是“指針的地址和指針的int值之間有什么區別”
並不是您要在這里實現的目標。 一個int僅包含32位值。 因此,(int)ptr將僅返回ptr地址的32位值,即您獲得的低4個字節。
C具有uintptr_t
,可讓您存儲指針值:
void *p = …;
uintptr_t u = (uintptr_t)p;
void *q = (void *)q;
// here q is equivalent to p
在許多平台上, u
像p
一樣存儲p
指向的對象的地址,並且u
和p
在內存中具有相同的表示形式。 這不是義務:允許C實現使用不同的表示形式。 但是使用相同的表示形式是滿足C標准要求的最明顯方法。
請注意,如果從仍然有效的指針獲得uintptr_t
值,則從uintptr_t
為指針類型只會提供可用的指針。 這可能是微妙的。 即使在表示形式相同的處理器體系結構上(幾乎都是它們),編譯器也可以假定您並沒有做太多瘋狂的事情,並相應地進行了優化。 有關一些示例,請參見對Cerberus調查的答復 。
在您的情況下,您沒有嘗試將指針值存儲在uintptr_t
,而是試圖將其存儲在int
。 這失敗了,因為在您的平台上, int
太小,無法存儲指針值。 顯然,在您的平台上,指針是64位值,而int
是32位值。 這是非常常見的安排。
a
是數組的地址。 (這是指向數組第一個元素的指針,並且在您的平台上,指針僅由地址表示。)。 在此特定運行中,它是0x7ffee8d30600。 那里沒什么特別的。 (int) a
地址轉換a
到一個int
值。 這是實現定義的。 您的實現執行通常的事情:由於int
太小,它會截斷該值。 將上述地址截斷為無符號的32位值將產生0xe8d30600
。 為了獲得帶符號的值,最高有效位變為符號位,因此a
恰好是負數: a
為-388823552
。 p
是(int *) ((int) a)
。 再次由實現定義此轉換,並且您的實現又執行與大多數操作相同的操作。 它以32位帶符號int
值-388823552
,它延伸到所需的寬度和它移位到無符號范圍,產生2 64 - 388823552 = 0xffffffffe8d30600。 (int)p
應用與上述(int)a
相同的截斷過程,並再次產生-388823552
。 但是,你正在使用的%x
說明符打印出來,所以這個值轉換為unsigned
,賦予值2 32(32-bit類型平台) - 388823552 = 0xe8d30600。 我明白了 機器基於64位地址。 將地址轉換為int值將丟失地址的高位值。 因此,此處a的地址與ptr的地址不同。
如果要在C ++中使用指針,我們可以使用intptr_t
或最好使用uintptr_t
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.