2017-04-21 52 views
1

我知道,在const int *ptr中,我們可以更改地址,但不能更改該值。即ptr將被存儲在讀寫部分(堆棧)中,並且對象或實體將被存儲在數據分段的只讀部分中。所以,我們可以改變指針ptr指向的地址,但不能改變常量的對象。const int * ptr = 500;其中存儲的確切位置

int main() 
{ 
    const int *ptr=500; 
    (*ptr)++; 
    printf("%d\n",*ptr); 
} 

輸出爲指定只讀位置* PTR

int main() 
{ 
    const int *ptr=500; 
    ptr++; 
    printf("%d\n",*ptr); 
} 

沒有編譯錯誤,但在運行時輸出爲「段錯誤」。

我同意第一個問題,爲什麼我在第二個問題上遇到分段錯誤?他們將在哪裏儲存?

+0

[應該密切相關](http://stackoverflow.com/a/43338131/2173917) –

+1

'const int * ptr = 500;'是標準C中的約束違規。gcc編譯器的行爲就像您寫'const int * ptr =(const int *)500;'如果您在標準兼容模式下調用編譯器,它將發出診斷信息。 –

+0

「o/p」是什麼意思? –

回答

5

分段錯誤的原因與您的想法不同。

它是而不是因爲const

這是幹什麼,因爲你不能訪問您試圖訪問該地區時*ptr

當你做出一個指向「東西」,你仍然沒有允許訪問數據(又名反引用指針),直到指針指向某個屬於你的內存。

實施例:

int x = 0; 
int* p = (int*)500; 

int a = *p; // Invalid - p is not pointing to any memory that belongs to the program 

p = &x; 
int b = *p; // Fine - p is pointing to the variable x 

p++; 
int c = *p; // Invalid - p is not pointing to any memory that belongs to the program 

「無效」 的代碼可以得到分割故障。另一方面,它也可能只是執行併產生意想不到的結果(或更糟糕的是:產生預期的結果)。

1
const int *ptr=500; // WRONG 

這聲明瞭一個局部變量,它是一個指向某個常量整數的指針。 const只是告訴編譯器它不允許更新(覆蓋)解引用的指針內存單元。

但是,您的代碼不正確;您可能想要:

const int *ptr = (const int*)500; 

指針初始化爲address 500(您初始化指針)。

在大多數系統中,該地址(以及後面的地址,例如自sizeof(int)起的地址504是4)不在virtual address space之中。所以解引用它(與*ptr)是undefined behavior,並且往往會給一些segmentation fault。另請參閱this

ptr將存儲在讀寫部分(堆棧)中,並且對象或實體將存儲在數據分段的只讀部分。

這是錯誤的。編譯時沒有做任何事情來將內存區保持在只讀text segment(但是,大多數編譯器將大部分文字或const靜態或全局數據在編譯時定義在其中)。只是你禁止編譯器更新指向的東西(沒有強制轉換)。

如果您在運行時需要只讀內存區域,則需要詢問您的操作系統(例如在Linux上使用mmap(2) & mprotect(2))。 BTW保護工作在pages

在Linux上,使用pmap(1)(或proc(5),例如,從您的程序中按順序讀取僞文件/proc/self/maps)。您可能需要的ptr任何非關聯化之前添加

char cmdbuf[64]; 
snprintf(cmdbuf, sizeof(cmdbuf), "pmap %d", (int) getpid()); 
system(cmdbuf); 

在你的代碼要明白什麼是它的虛擬地址空間。

嘗試

cat /proc/self/maps 

cat /proc/$$/maps 

,並瞭解它們的輸出(注意$$擴展到你的shell的PID)。也許你也在你的錯誤程序上試驗strace(1)(你應該用gcc -Wall -g編譯)。

+0

「指針初始化爲地址500(您初始化指針)」。不,指針不允許用C中的整數初始化。它們只能通過地址初始化。要獲得地址500,在初始化之前,您必須將整數常量轉換爲指針類型。 – Lundin

1

這裏有很多混淆。

和對象或實體將存儲在只讀數據segement

否的部分中,存在用於所指向在對象的存儲位置沒有要求。這僅在聲明指向對象時由任何限定符/說明符(例如conststatic)確定。

const int * ptr = 500;

這是無效的C代碼必須導致編譯器消息。一個整數不能被分配給一個指針,它們之間必須有一個轉換。 GCC在這裏有一個已知的缺陷,你必須將它配置成一個標準的編譯器。 gcc -std=c11 -pedantic-errors

如果你有代碼如const int *ptr=(int*)500;這是有效的C,那麼它將設置指針指向地址500.如果在地址500有int,代碼將正常工作。如果在那裏你沒有被允許訪問的內存,那麼你會得到一些實現定義的行爲,比如崩潰 - 內存映射超出了語言的範圍。

(* ptr)++;

這是無效的C代碼必須導致編譯器消息。您不允許修改只讀位置。

總的來說,你的編譯器配置似乎很差。 GCC,正確配置,給出2個編譯器錯誤。

+0

謝謝你...我澄清了我的懷疑... – sravanthi