本文大部分知識點來自於互聯網,對這些知識歸納彙總結合自己的理解進行闡述。關於指針、指針數組、數組指針、函數指針、運算符優先級等等基本小知識點剖析。
一、 優先級列表
C優先級列表
Precedence | Operator | Description | Example | Associativity |
1 |
() |
Grouping operator |
(a + b) / 4; |
left to right |
2 |
! |
Logical negation |
if( !done ) ... |
right to left |
3 |
->* |
Member pointer selector |
ptr->*var = 24; |
left to right |
4 |
* |
Multiplication |
int i = 2 * 4; |
left to right |
5 |
+ |
Addition |
int i = 2 + 3; |
left to right |
6 |
<< |
Bitwise shift left |
int flags = 33 << 1; |
left to right |
7 |
< |
Comparison less-than |
if( i < 42 ) ... |
left to right |
8 |
== |
Comparison equal-to |
if( i == 42 ) ... |
left to right |
9 |
& |
Bitwise AND |
flags = flags & 42; |
left to right |
10 |
^ |
Bitwise exclusive OR |
flags = flags ^ 42; |
left to right |
11 |
| |
Bitwise inclusive (normal) OR |
flags = flags | 42; |
left to right |
12 |
&& |
Logical AND |
if( conditionA && conditionB ) ... |
left to right |
13 |
|| |
Logical OR |
if( conditionA || conditionB ) ... |
left to right |
14 |
? : |
Ternary conditional (if-then-else) |
int i = (a > b) ? a : b; |
right to left |
15 |
= |
Assignment operator |
int a = b; |
right to left |
16 |
, |
Sequential evaluation operator |
for( i = 0, j = 0; i < 10; i++, j++ ) ... |
left to right |
C++優先級列表
Precedence | Operator | Description | Example | Associativity |
1 |
() |
Grouping operator |
(a + b) / 4; |
left to right |
2 |
! |
Logical negation |
if( !done ) ... |
right to left |
3 |
->* |
Member pointer selector |
ptr->*var = 24; |
left to right |
4 |
* |
Multiplication |
int i = 2 * 4; |
left to right |
5 |
+ |
Addition |
int i = 2 + 3; |
left to right |
6 |
<< |
Bitwise shift left |
int flags = 33 << 1; |
left to right |
7 |
< |
Comparison less-than |
if( i < 42 ) ... |
left to right |
8 |
== |
Comparison equal-to |
if( i == 42 ) ... |
left to right |
9 | & | Bitwise AND | flags = flags & 42; | left to right |
10 | ^ | Bitwise exclusive OR | flags = flags ^ 42; | left to right |
11 | | | Bitwise inclusive (normal) OR | flags = flags | 42; | left to right |
12 | && | Logical AND | if( conditionA && conditionB ) ... | left to right |
13 | || | Logical OR | int i = (a > b) ? a : b | left to right |
14 | ? : | Ternary conditional (if-then-else) | if( conditionA || conditionB ) ... | right to left |
15 |
= |
Assignment operator |
int a = b; |
right to left |
16 | , | Sequential evaluation operator | for( i = 0, j = 0; i < 10; i++, j++ ) ... | left to right |
二、 指針數組和數組指針
指針數組:首先它是一個數組,數組的元素都是指針,數組佔多少個字節由數組本身決定。它是“儲存指針的數組”的簡稱。
數組指針:首先它是一個指針,它指向一個數組。在32 位系統下永遠是佔4 個字節,至於它指向的數組佔多少字節,不知道。它是“指向數組的指針”的簡稱。
下面到底哪個是數組指針,哪個是指針數組呢:A) int *p1[10]; B) int (*p2)[10];
這裏需要明白一個符號之間的優先級問題。優先級參看第一點。“[]”的優先級比“*”要高。p1 先與“[]”結合,構成一個數組的定義,數組名爲p1,int *修飾的是數組的內容,即數組的每個元素。那現在我們清楚,這是一個數組,其包含10 個指向int 類型數據的指針,即指針數組。至於p2 就更好理解了,在這裏“()”的優先級比“[]”高,“*”號和p2 構成一個指針的定義,指針變量名爲p2,int 修飾的是數組的內容,即數組的每個元素。數組在這裏並沒有名字,是個匿名數組。那現在我們清楚p2 是一個指針,它指向一個包含10 個int 類型數據的數組,即數組指針。我們可以藉助下面的圖加深理解:
三、 函數和指針
3.1 指針函數
這個比較簡單此處不做過多闡述。指針函數就是返回指針的函數,一般定義形式如下:
類型名 *函數名(函數參數表列);
例: const char* strcpy(char* strDest, const char* strSrc);理解:“()”的優先級高於“*” ,故 strcpy 先於 "()" 結合表明這是一個函數,再與 "*"結合表明返回一個指針。前面 const char 表明函數 strcpy 返回的就是一個 const char 類型指針。
3.2 函數指針
函數指針是指向函數的指針變量,即本質是一個指針變量。一般定義形式如下:
類型名 (*函數名)(參數);
例 : int (*p_func)(char*);理解:p_func先與“*”結合表明這是一個指針變量,後面“()”表明該指針指向一個函數,char*
strdata 是該函數的參數,前面的 int 是該函數的返回值。
關於調用問題:假定有函數 int func(char* strdata); 要調用該函數可直接 func(str) ; 也可用函數指針調用。調用形式如下:
p_func = func; // 賦值
(*p_func)(str); // 調用
3.3 返回函數指針的函數
先來看一個表達式,void (*signal(int signo, void (*func)(int)))(int);這是Linux的一個聲明(先不說這是函數還是指針),當然你可以谷歌它。如果你能完全理解並能隨心所欲寫類似代碼那麼你不用看這篇文章了,這是在浪費你時間。
有一類函數,返回指針不過返回的是指向函數的指針。一般定義形式如下:
類型名 (*函數名(函數參數列表))(函數參數列表);
例:int (*func(char a, short b))(int); 理解:按優先級來一步一步解析該聲明。func先和右邊的“()”結合表明 func 是一個函數,然後和“*”結合意味着它是一個指針函數。作爲一個指針函數(見3.1)就要有它的返回值。現在來看 func 的返回值,最右邊的“()”表示它要指向一個函數。這個函數的形式是 int funcname(int) 。
用 typedef 關鍵字會使該聲明更簡單易懂。int (*p_type)(int); 此處 p_type 是一個函數指針變量。 typedef int (*p_type)(int); 此時 p_type 就成爲了一個函數指針類型。int (*func(char a, short b))(int); 就可以寫爲 p_type func(char a, short b);
然後來看剛剛給出的 void (*signal(int signo, void (*func)(int)))(int); 理解:signal 是一個函數, 第二個參數是一個函數指針,指向 void funcname(int x) 類型的函數, signal 的返回值是一個函數指針,指向 void funcname(int x) 類型的函數。爲什麼要這麼設計?這麼設計有什麼好處?signal 函數是處理信號的函數,作用相當於消息映射。他要指名信號 signo 對應的處理函數即 func 指向的函數。返回值爲什麼要和 func 一樣?看 const char* strcpy(char* strDest, const char* strSrc) 的返回值就一清二楚了。