2013-08-06 20 views
2

在C中創建常量字符串的好方法是什麼?通過對其索引位置之一進行字符分配不能突變的字符串。並且在初始化後的後續執行中不能被另一個字符串替換的字符串。在C中使用char *和char []表示常量字符數組的差別

我在以下代碼中嘗試了char *和char []。我嘗試了使用和不使用「const」關鍵字。結果是非常奇怪的。

以下是我的代碼:

#include <stdio.h> 
main() { 
    char a []= "abc" "def"; 
    char* b = "abcdef"; 
    const char c [] = "abcdef"; 
    const char* d = "abcdef"; 

    a[1] = 'y'; 
    b[1] = 'y'; 
    c[1] = 'y'; 
    d[1] = 'y'; 
    printf("%s %s %s %s \n", a, b, c, d); 

    a = "overwrited"; 
    b = "overwrited"; 
    c = "overwrited"; 
    d = "overwrited"; 
    printf("%s %s %s %s \n", a, b, c, d); 
} 

結果是 在第一個printf,所有的a,b,C,d可以被突變;但c和d會顯示警告「只讀位置的分配」。 在第二個printf中,a和c都返回錯誤。但是b和d被另一個字符串順利地替換並且變得「過時」。

我對這個結果非常困惑,好像「const」關鍵字對字符串賦值沒有影響;但它對索引字符變異有影響。 char []和char *也顯示不同的行爲。有人能向我解釋這個背後的機制嗎?

+2

@GregHewgill:我建議你再看一遍,這個問題不是那個問題的重複。 – caf

+1

[char * str'和'char str []'之間的區別以及兩者如何在內存中存儲?](http://stackoverflow.com/questions/15177420/what-does-sizeofarr-return/15177499#15177499) –

+0

@GrijeshChauhan你的鏈接已經啓發了我的差異btw char *和char []。我在我的問題中添加了一些更多的代碼,以便使它涵蓋更多「常量」概念。 – Erencie

回答

3

如果你想最大化你的const陣列將被放置到實際只讀存儲器的機會,你應該讓他們static還有:

static const char c[] = "abcdef"; 

這是因爲自動存儲時間所有變量通常在相同的內存區域中創建,無論它們是否爲const - 是否合格。因此這個內存區域不能被設置爲只讀。

但是,考慮到您的實現顯然不會將字符串文字放入只讀內存中,它可能根本不會使用只讀內存,並且警告可能是您希望的最好的。如果您使用的是基於gcc的編譯器,則還可以嘗試使用-fno-writable-strings編譯器選項。


的原因,這兩個線是錯誤:

a = "overwrited"; 
c = "overwrited"; 

是因爲ac是陣列和陣列不能直接分配給具有=操作者(無論它們是否是const或不)。變量聲明中的=不是=運算符 - 它只是初始化語法的一部分,並且數組可以初始化

的原因,這些行是行:

b = "overwrited"; 
d = "overwrited"; 

是因爲bd是不恆定的指針不斷char秒。這些分配不會改變bd指向的原始字符串 - 它們將bd更改爲指向不同的字符串(實際上可能是相同的字符串)。

如果你想bd是恆定的指針(使指針本身不能改變),您可以更改聲明:

char * const b = "abcdef"; 
const char * const d = "abcdef"; 

..和工作分配到bd至少應從編譯器發出錯誤消息。

+0

你的意思是,在一個方法中,即使我添加了「const」關鍵字,字符串仍然可能不是一個常量,因爲它會在不是隻讀的內存區域內創建。這聽起來很相似。根據我對其他語言的經驗,如果我添加一個常量關鍵字,那麼該字符串將是「固定的」。 – Erencie

+0

@Erencie:在C語言中,它意味着編譯器*被允許*使其成爲只讀的,並且這是程序嘗試更改它的錯誤。作爲效率的折衷,C對實現必須處理錯誤程序的要求很少 - 某些錯誤(如直接分配給const限定對象)需要在編譯時發出錯誤消息(以及「warning 「來自編譯器的消息滿足這一點),但這是關於它的 - 如果需要,實現可以繼續併產生不正確的可執行文件。 – caf

-1

1常數

你可以使用該指令

\#define CONST_NAME value 

然後在你的代碼文件中使用CONST_NAME。預處理器將用值 替換CONST_NAME的實例。另外,在表示字符數組或C中的字符串時,和char []有什麼區別?

2.字符*和炭[]

字符*是指向的對象是字符類型。沒有固定的大小。 char *指向您的「字符串」的第一個字符。

char []是一個固定大小的字符數組。

通常情況下,管理char數組比指針更容易。但是當你不知道你的「字符串」的大小時,我們是一個指針。

我推薦閱讀指針。這是什麼C是關於:)

1

const char cconst char* d都是恆定和只讀的位置,你試圖分配新的東西。你的編譯器的警告實際上是我的錯誤(gcc 4.4.3)。

1)不要忽視警告。

2)修改字符串字面量是不確定的行爲。(幸好你得到預期的輸出,但它並不意味着你是允許的。)

3)增加你的編譯器警告和錯誤的嚴格程度。

+0

我正在使用一個名爲「tiny C編譯器」的編譯器,因爲我正在尋找輕量級的C編譯器,以便我可以快速播放一些C編碼。你是對的。警告不應該被忽視;這一切都取決於編譯器設置中的嚴格級別。 – Erencie

+0

'd'本身並不是一個常量 - 它是一個常量的非常量指針。 – caf