聲明符:
這是第一個觀點:
C和C++的每一個聲明都有兩個主要的部分:一串0個或多個聲明修飾符+一串0個或多個聲明符(多個申明符用逗號分開)例如:
Static unsigned long int *x[N];
(Declarationg specifier )(declarator)
聲明符就是要聲明的名字,經常與像*,[],()和&((在C++中)組合在一起。在聲明符中這個符號*意味着“指向”,[]意思是“數組”。因此,*x[N]是一個聲明符說明x是一個有N個指針元素組成的數組,類型是在類型修飾符中指定的類型。例如,
Static unsigned long int *x[N];
將x聲明爲這種類型的對象:“有N個指向無符號長整型元素組成的數組。“
我怎麼知道*x[N]是一個指針數組而不是指向數組的指針呢?
它遵循這個原則:在聲明符組中操作符的優先級與他們在表達式中的一致。
例如:[]比*的優先級高。因此,在這個聲明符中*x[N]意味着x 首先是一個數組,然後纔是它的元素是一個指針。
圓括號:();在聲明符中有兩個作用:
一是作爲函數調用操作符;
二是分組。
作爲函數調用操作符時,()與[]的優先級相同,分組時()擁有最高的優先級。
例如,*f(int)是一個聲明符,指定f是一個返回指針類型的函數。而(*f)(int)指定f是指向一個函數的函數指針。
聲明符可能包含不止一個標識符。這個聲明符*x[N]包含兩個標識符,x和N。
只有一個標識符是被聲明的,被稱爲聲明ID。其他的,如果還有的話,必須似乎在之前聲明的了。例如在這個聲明符中x是聲明ID。
聲明限定符
一些聲明限定符可以是類型限定符諸如int,unsigned或者是一個新類型的標識符。他們也可以使存儲類限定符像extern或者static。在C++中他們也可以是函數限定符像inline或者virtual。
下面是另一個觀點:
類型限定符作用於聲明符ID的類型,其他的限定符提供非類型信息,這些信息直接作用於聲明ID。
例如:static unsigned long int *x[N];
聲明x爲一個變量類型:“由N個指向無符號長整型的指針組成的數組。“ ;關鍵字static限定x爲靜態分配的內存。
下面是另一個重要的觀點:
聲明限定符在聲明中的順序是無關緊要的。例如:
Const VP vectorTable[]
等價於
VP const vetorTable[]
const void* vetorTable[]
等價於
void const* vetorTable[]
我們大多數人將諸如static這樣的存儲類限定符(最左邊)作爲第一個聲明限定符,但是這只是一個慣例,不是語言本身的要求。
聲明限定符const和volatile是不同的:唯一的聲明限定符也能出現在聲明符中的是const和volatile。
例如:在void*const vectorTable[]中的const出現在了聲明符中。
在這中情況下,你就不能重新組織關鍵字的順序,例如:*const void vetorTable[]是錯誤的。
對於編譯器來說聲明限定符的順序是無關緊要的。於是這兩種聲明是等價的:
const void *vetorTable[];
和
void const *vectorTable[];
幾乎所有的C和C++編程者都傾向於將const和volatile寫在類型限定符的左邊。我更喜歡將他們寫在右邊,並且我強烈推薦寫在後邊的這種寫法。
儘管一般C和C++是從左到右, 從上到下讀的,讀指針聲明的時候,在某種意義上說,是相反的。也就是說,指針聲明是從右到左讀的。
通過將const置於其他類型限定符的右邊,你可以嚴格的從右到左讀指針聲明,並且將const出現在右邊的位置。
例如:
T const *p;
<------------
將p聲明爲指向cons T 的指針;
並且:
T *const p;
<------------
將p聲明爲指向T的const指針。
將const寫在其他聲明限定符之後實際上使得更加容易看到const和typedef結合的效果。
Typedef void* VP;
Const VP vectorTable[];
一種轉化是象下面這樣置換VP:
Const (VP )vectorTable[]
Const(void*)vetorTable[]
使得它看起來vectorTable具有這種類型“指向const void 的指針數組“,這是錯誤的,
正確的轉換是將VP置換爲:
const (VP) vectorTable[]
(void *)const vectorTable[]
也就是說,vectorTablel是指向void的const指針數組,但是它卻不是顯然的。
將const寫在聲明限定符的最右邊使得更容易看到正確的翻譯,
(VP) const vectorTable[];
(void *)const vectorTable[];
現在我意識到我正在推薦一種其他人很少用的風格,其他人都會將const放在左邊;
但是,鑑於很少有C和C++的程序員知道在聲明中使用const時自己在做什麼,每個人都不這樣做是支持現在流行風格。爲什麼不抵制這種趨勢。嘗試着使用一種更加清晰的風格呢?
只要我還從事着這個職業,我就會一如既往的支持這種風格。儘管這對大多數程序員還沒有任何影響,但是很多人還是養成了書寫的壞習慣。
Const int *p;(更加規範化)
而不是
Constint* p;
也就是說,他們將空格和*作爲聲明限定符而不是聲明符,我真的相信程序員這樣書寫給他們自己和其他人造成麻煩。
當然,空格對編譯器毫無影響,但是將空格置於*之後會給人關於聲明的內在結構造成一種錯誤的印象。
---------------------------------------------------------------------------------------------------------
const的作用
const是C語言的一種關鍵字,起受保護,防止以外的變動的作用!可以修飾變量,參數,返回值, 函數體。
const可以提高程序的健壯性,你只管用到你想用的任何地方。
1、如果輸入參數是指針型的,用const修飾可以防止指針被意外修改。
2、如果參數採用值傳遞的方式,無需const,因爲函數自動產生臨時變量複製該參數。
3、非內部數據類型的參數,需要臨時對象複製參數,而臨時對象的構造,析構,複製較爲費時,因此建議採用前加const的引用方式傳遞非內部數據類型。而內部數據類型無需引用傳遞。
1、函數返回const指針,表示該指針不能被改動,只能把該指針賦給const修飾的同類型指針變量。
2、函數返回值爲值傳遞,函數會把返回值賦給外部臨時變量,用const無意義!不管是內部還是非內部數據類型。
3、函數採用引用方式返回的場合不多,只出現在類的賦值函數中,目的是爲了實現鏈式表達。
class stack
{
public:
int GetCount(void) const ;
private:
int m_num;
};
int stack::GetCount(void) const
{
m_num++;
}
編譯器輸出錯誤信息:error C2166: l-value specifies const object。
1、const char *p 表示 指向的內容不能改變
2、char * const p,就是將P聲明爲常指針,它的地址不能改變,是固定的,但是它的內容可以改變。
3、這種const指針是前兩種的結合,使得指向的內容和地址都不能發生變化.
const double pi = 3.14159;
const double *const pi_ptr = π