[英]Are memory addreses portable in C?
假設我們有程序 1...
./程序1
int main(int argc, char *argv[])
{
int *i;
*i = 10;
printf("%lld", i);
return 0;
}
現在程序2...
./program2 program1output 10
int main(int argc, char *argv[])
{
int *t;
t = (int*)atoll(argv[1]);
*t = atoi(argv[2]);
return 0;
}
這會起作用嗎? 你可以在不同的程序之間共享內存地址嗎?
這種行為不是由 C 標准定義的。 在任何通用多用戶操作系統上,每個進程都有自己的虛擬地址空間。 除了某些共享內存外,分配給進程的所有內存都與分配給其他進程的內存分開:
在專用操作系統中,不同的進程可以共享一個地址空間。
這不是正確的代碼:
int *i;
*i = 10;
聲明int *i;
將i
定義為指針,但不為其分配值。 然后使用*i
是不合適的,因為它試圖引用i
指向的位置,但i
沒有被分配指向任何東西。
要定義一個int
並使其地址在輸出中可見,您可以定義int i;
然后打印&i
。
這不是打印地址的正確方法:
printf("%lld", i);
要打印地址,請將其void *
轉換為void *
並使用%p
對其進行格式化。 格式化的結果是實現定義的:
printf("%p", (void *) &i);
這不是重建地址的好方法:
int *t;
t = (int*)atoll(argv[1]);
與printf
,類型應該是void *
,並且嘗試使用atoll
進行轉換時會出現問題。 C 標准不保證它會起作用; 用%p
打印產生的格式可能不是正常的整數格式。 相反,將%p
說明符與sscanf
:
void *temp;
if (1 != sscanf(argv[1], "%p", &temp))
exit(EXIT_FAILURE);
int *t = temp;
當地址來自其他進程時, sscanf
轉換的行為不是由 C 標准定義的。
原則上,應用程序在其自己的/私有內存上運行。 有多種方法可以在不同的進程之間共享內存,但這需要特殊的機制來克服上述“主要”(例如內存映射文件)。 有在短期看,例如, 該文章共享內存。
在您的情況下,程序一將結束並且其內存不再可用; 並且您訪問它的方式絕對不是訪問共享內存所需的“特殊機制”之一:
盡管整數值可以轉換為指針值,但僅當整數值最初從指針轉換為有效對象時,訪問該指針才有效。 在您的示例中情況並非如此,因為在t = (int*)atoll(argv[1]);
計算的積分值t = (int*)atoll(argv[1]);
從未指向當前程序中的有效對象。
通常,內存地址與進程相關聯,因為每個進程可能有自己的內存空間。 因此,地址是虛擬地址而不是物理地址,這意味着它們是對進程內存空間中某個位置的引用,而不是對芯片上某個位置的引用。
(並非所有環境都有虛擬內存。例如,嵌入式系統可能沒有。)
如果有兩個程序在同一個進程中運行,則可以在它們之間傳遞一個指針。 例如,主程序可以傳遞一個指向它加載的動態鏈接庫的指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.