2012-08-15 76 views
0

我最近了解到可以使用指針更改c中常量的值,但不可能用於字符串文字。可能的解釋是,常量和其他字符串在空間中的可修改區域中被分配了空間,而字符串文字在空間中被獲取了不可修改的區域(可能是代碼段)。我寫了一個程序,顯示這些變量的地址。輸出也被顯示。常量,文字和全局變量獲取空間的地方

#include <stdio.h> 
int x=0; 
int y=0; 

int main(int argc, char *argv[]) 
{ 
    const int a =5; 
    const int b; 
    const int c =10; 
    const char *string = "simar"; //its a literal, gets space in code segment 
    char *string2 = "hello"; 
    char string3[] = "bye"; // its array, so gets space in data segment 
    const char string4[] = "guess"; 
    const int *pt; 
    int *pt2; 

    printf("\nx:%u\ny:%u Note that values are increasing\na:%u\nb:%u\nc:%u Note that values are dec, so they are on stack\nstring:%u\nstring2:%u Note that address range is different so they are in code segment\nstring3:%u Note it seems on stack as well\nstring4:%u\n",&x,&y,&a,&b,&c,string,string2,string3,string4); 
} 

enter image description here

請解釋正是這些變量得到空間? 全局變量在哪裏獲得空間,常量在哪裏得到,字符串文字在哪裏得到?

+0

「size a.out」可用於驗證Steve的答案(僅在某種程度上)。 – Ram 2012-08-15 12:14:04

回答

5

「可能」顯示了該情況。

您可以編寫試圖修改常量對象的代碼(例如將其地址轉換爲指向非常量類型的指針)。您也可以編寫試圖修改字符串文字的代碼。

在這兩種情況下,您的代碼都有未定義的行爲,這意味着標準不關心發生了什麼。實現可以做它喜歡的事情,發生的事情通常是其他事情的偶然副作用。你不能依靠這種行爲。簡而言之,該代碼是錯誤的。定義爲const的對象和字符串文字都是如此。

它可能是在一個特定的實現,效果是改變對象或文字。這可能是在另一個實現中,您會遇到訪問錯誤並且程序崩潰。這可能是在第三次執行時,您有時會得到一種行爲,而在其他時間會得到一種行爲。可能會發生完全不同的事情。

這是實現特定的變量哪裏得到他們的空間,但在一個典型的實現:

  • xy處於修改的數據段
  • a是在棧上。如果不是因爲您接收到地址,則可以將變量存儲完全優化,並且值5用作編譯器針對使用a的代碼發出的任何CPU指令中的立即值。
  • b我認爲是一個錯誤 - 未初始化的const對象。也許這是允許的,但編譯器可能應該警告。
  • c在堆棧上,與a相同。
  • 文字「simar」等都是在代碼段,只讀數據段或可修改的數據段,如果實現不打擾rodata。
  • string3string4是堆棧上的數組。每個都通過複製字符串文字的內容來初始化。
1

我最近發現它可以使用指針

這樣做改變在C常量的值會導致不確定的行爲(參見6.7.3標準),這意味着任何事情都有可能發生。實際上,您可以在一些基於RAM的系統上修改常量。

它不可能字符串文字

這同樣是不確定的行爲,並可以正常工作,或可能無法正常工作,否則可能會導致藍煙從你的硬盤上升。

可能的解釋在於,常量和其他字符串空間分配空間中修改的區域,而字符串字面量獲取不可修改的區域在空間

這取決於系統的事實。在某些系統中,它們都位於恆定/虛擬RAM段中,有些系統可能位於非易失性閃存中。討論一下事情在內存中的位置是毫無意義的,而沒有說明你在說什麼系統。沒有通用的情況。