[英]pointer typecasting
int main()
{
int *p,*q;
p=(int *)1000;
q=(int *)2000;
printf("%d:%d:%d",q,p,(q-p));
}
輸出
2000:1000:250
1.我無法理解p=(int *)1000;
行,這是否意味着p指向1000個地址位置? 如果我做*p=22
,該值存儲在1000個地址並覆蓋現有值怎么辦? 如果它覆蓋該值,那么如果另一個程序正在使用1000地址空間怎么辦?
qp=250
如何? 編輯:我試過printf("%u:%u:%u",q,p,(qp));
輸出是相同的
int main()
{
int *p;
int i=5;
p=&i;
printf("%u:%d",p,i);
return 0;
}
輸出
3214158860:5
這是否意味着p指向1000個地址位置?
是。
如果我做* p = 22怎么辦
它正在調用未定義的行為-您的程序很可能會因段錯誤而崩潰。
請注意,在現代操作系統中,地址是虛擬的-您不能像這樣覆蓋其他進程的地址空間,但是可以嘗試在自己進程的地址空間中寫入無效的內存位置。
qp = 250如何?
因為指針算法的工作原理是這樣的(為了與數組索引兼容)。 兩個指針的區別是它們的值之差除以sizeof(*ptr)
。 類似地,將n
添加到類型T
的指針ptr
會得到數值ptr + n * sizeof(T)
。
這是否意味着編譯器使用的地址是整數?
甚至沒有必要“由編譯器使用”部分。 地址是整數,它只是C語言的一種抽象,我們有很好的指針來簡化我們的生活。 如果您使用匯編語言進行編碼,則只需將它們視為無符號整數即可。
順便說一下
printf("%u:%d", p, i);
也是未定義的行為- %u
格式說明符期望unsigned int
,而不是指針。 要打印指針,請使用%p
:
printf("%p:%d", (void *)p, i);
是的,使用*p=22
您將寫入1000個地址。
qp
是250,因為int的大小是4,所以它是2000-1000 / 4 = 250
p = (int *) 1000
的含義是實現定義的。 但是,是的,在典型的實現中,它將使p
指向地址1000
。
之后執行*p = 22
確實會嘗試將22
存儲在地址1000
。 但是,在一般情況下,這種嘗試將導致不確定的行為,因為不允許您僅將數據寫入任意內存位置。 您必須以一種或另一種方式分配內存才能使用它。 在您的示例中,您沒有做出任何努力來分配地址1000
任何內容。 這意味着您的程序很可能會崩潰,因為它試圖將數據寫入未正確分配的內存區域。 (此外,在許多平台上,為了通過指針訪問數據,這些指針必須指向正確對齊的位置。)
即使您以某種方式成功完成了在地址1000
處寫入22
,也並不意味着它將以任何方式影響“其他程序”。 在某些舊平台上(例如DOS,例如)。 但是現代平台為每個正在運行的程序(進程)實現了獨立的虛擬內存。 這意味着每個正在運行的進程都有其自己的單獨地址1000
並且看不到另一個程序的地址1000
。
是的, p
指向虛擬地址1000 *p = 22;
,您很可能會遇到細分錯誤; 通常,整個前1024個字節對於讀取或寫入都是無效的。 假設您有虛擬內存,它不會影響其他程序; 每個程序都有其自己的虛擬地址空間。
q - p
的值是兩個地址之間的sizeof(*p)
或sizeof(*q)
或sizeof(int)
的單位數。
將任意整數強制轉換為指針是未定義的行為。 任何事情都可能發生,包括什么都沒有,分段錯誤或無聲地覆蓋其他進程的內存(在現代虛擬內存模型中不太可能)。
但是我們曾經在DOS實模式下使用過這樣的絕對地址來訪問中斷表和BIOS變量:)
關於qp == 250
,這是指針算術語義的結果。 在您的系統中, sizeof int
顯然是4。 因此,當您將1加到int指針時,它實際上會增加4,因此它指向下一個int
而不是下一個字節。 此行為有助於陣列訪問。
does this mean that p is pointing to 1000 address location?
是。 但是這個1000地址可能屬於其他一些進程地址。在這種情況下,您非法訪問了另一個進程的地址空間的內存。 這可能會導致分割錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.