2016-10-10 135 views
3

例如,爲什麼不:的爲什麼C中的字符串用'const'聲明?

char *s= "example"; 

代替:

const char *s= "example"; 

我的理解是常量使得它不變的,但爲什麼在編譯時首先我收到一個錯誤?

此外,如何構思應用於

int * x; 

VS

const int *x; 

我看到第二個使用得更多,是它使用良好做法「利弊詮釋*」?

+2

因爲你不能修改字符串文字。 –

+0

,這並不能解釋爲什麼它不能被修改。由於char * s =「example」應該只給出一個字符數組。我明白你不應該,但它不能解釋爲什麼你不能。 –

+0

我不認爲你第一個出現錯誤,它是有效的。 – krato

回答

12

沒有要求使用const,但它是一個好主意。

在C中,一個字符串文字是char[N]類型,其中N是串的長度加上1(用於終接'\0'空字符)的表達。但試圖修改與字符串文字相對應的數組具有未定義的行爲。許多編譯器會將該陣列存儲在只讀存儲器中(不是物理ROM,而是由操作系統標記爲只讀的存儲器)。 (數組表達式在大多數情況下轉換爲指向數組對象的初始元素的指針表達式。)

使字符串文字const更有意義,但const關鍵字在舊時不存在C版本,它會破壞現有的代碼。 (C++確實使字符串文字const)。

此:

char *s= "example"; /* not recommended */ 

實際上是用C完全有效的,但它是潛在的危險。如果在這個聲明之後,你這樣做:

s[0] = 'E'; 

然後你試圖修改字符串,行爲是未定義的。

此:

const char *s= "example"; /* recommended */ 

也是有效的;通過評估字符串文字得到的char*值安全且安靜地轉換爲const char*。它通常比第一個版本更好,因爲如果您嘗試修改字符串文字(在編譯時比在運行時捕獲錯誤更好),它可以讓編譯器警告您。

如果您的第一個示例出現錯誤,那麼很可能是您無意中將代碼編譯爲C++而不是C語言,或者您使用的是gcc的-Wwrite-strings選項或類似的選項。 (-Wwrite-strings使得字符串文字const;它可以提高安全性,但它也可引起GCC拒絕,或至少警告,有效的C代碼)

+0

可能值得注意的是,給定'char s1 [] =「example」; char s2 [] =「example」;'每個變量都會得到自己的數組,其中包含字符串「example」,並且這兩個副本可以獨立修改,但給出'char * p1 =「example」; char * p2 =「example」;'這兩個指針都可能標識* same *數組;即使內存不受寫保護,修改一個指針的目標也可能會修改另一個指針(或其他任何以「example」中的部分或全部字符結尾的字符串)的目標。 – supercat

+0

給定一些string.h庫函數的上下文,例如char * strcat(char * dest,const char * src),連接字符串的函數不會返回值,第一個參數是'unsafe 「? –

+1

@ B.Li:'strcat'返回的值只是'dest'參數的值。如果其中一個參數爲空或其他無效指針,或者目標陣列沒有空間,則可能是不安全的。如果這就是你的想法,那麼沒有常量正確性問題。 –

2

與警告級別4的Visual Studio 2015年,這個編譯和運行是否編譯爲C或C++:

#include <stdio.h> 

char *s1= "example\n"; 
const char *s2= "example\n"; 

int main(int argc, char **argv) 
{ 
    printf(s1); // prints "example" 
    s1[2] = 'x'; 
    printf(s1); // prints "exxmple" 

    printf(s2); 

    return 0; 
} 

如果我加入這一行,它將無法編譯C或C++與每一個編譯器我知道:

s2[2] = 'x'; // produces compile error 

這是const關鍵字旨在避免的錯誤。它只是告訴編譯器不允許分配指向的對象。

如果您的指針指向charint或其他任何內容,則無關緊要。 const關鍵字對所有指針具有相同的效果,這就使得它不可能(很好,很難)分配給const

0

字符串文字用作值編譯成的char的數組不應該被修改。試圖修改它會調用未定義的行爲。由於向後兼容的歷史原因,其類型爲char [],但實際上應該是const char []。您可以啓用額外的編譯器警告來更改此信息,並指示編譯器將這些字符串視爲const