2015-12-21 86 views
4

我正在通過玩具問題來理解C和C中指針和數組之間的區別,我偶然發現了一些我還沒有尋找或尋找答案。(* b)[0] vs * b [0] - 數組和指針

我有以下程序

#include <stdio.h> 

int main() 
{ 
    int a[3][3] = {{1, 2, 3}, {4, 5,6}, {7, 8, 9}}; 
    int (*b)[3]; 

    b = a; 

    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 
    printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

    b++; 
    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

    b++; 
    printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

    return 0; 
} 

當我編譯並運行它,我得到這個:

[email protected]: clang -g q.c -o q.o                  
[email protected]: ./q.o 
1 2 3 
1 4 7 
4 5 6 
7 8 9 

我的問題是什麼(*b)[0]*b[0]之間的區別?看起來前者是int *型,而後者是int *[3]型。如何解釋操作人員*[]()來認識這一點?

回答

3

int (*b)[3];是一個數組指針,一種特殊類型的指針,可以指向整個數組而不僅僅指向第一個元素。不要與int *b[3]混淆,這是一個3個指針的數組,並且不存在於您的代碼中。

b=a將b設置爲指向二維數組a中的第一個元素,它是一維數組。

當您取消引用數組指針時,您將獲得數組。當一個數組在表達式中使用時,它將「衰減」爲指向第一個元素的指針,這解釋了第一個printf行。

如果你寫*b[0],那麼[]的運算符優先級高於*,所以它的意思是「給我數組編號0,它會衰減成指向第一個元素的指針,給我該元素的內容」。

對於任何指針類型,包括數組指針,指針增量爲b遵循指針算術規則:增加地址,以便指針指向內存中下一個相鄰類型的指針。也就是說,在這個例子中增加地址sizeof(*b)字節,這將是3*sizeof(int)

+0

啊,我應該有一個知道我曾經寫過運算符來考慮運算符的優先級。你的回答爲我清除了一些事情。 – Idr

0

(*b)[0]首先解引用指針,然後做索引訪問。它相當於*((*b)+(0))

*b[0]先做索引訪問然後解引用指針。它相當於**((b)+(0))

加零意味着什麼都沒有,所以他們都相當於**bint型,所以幾乎沒有任何區別。

2

這隻適用於二維數組,而不適用於任何隨機指針。

當使用(*b)[1]時,首先完成解引用,然後是索引,所以它實際上意味着b[0][1],並且您從第一個數組中獲取值。

如果您使用*b[1],它與*(b[1])相同。索引操作符將首先被處理,然後被解引用,所以你得到了b[1][0]

1

我的問題是(* b)[0]和* b [0]之間的區別是什麼?

int (*b)[3] ;是指針大小3的一個維陣列。在這種情況下,第一取消引用指針,然後執行由於()索引訪問。

*b[3]是3個指針的數組,在這種情況下首先做索引訪問,因爲[];因爲這一點

當在第一printf

printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

正在打印第一一個維陣列的元件在第二printf它指向每一行的第一個元素。

b++在第一種情況下指向第二個數組,第二種情況是printf它指向每行的第二個元素。

0

b是指向數組s的指針。在作業中

b = a; 

a將衰減爲指向其第一個元素。由於a是一組數組,因此它的第一個元素是和數組3int s。因此,上面的語句相當於

b = &a[0]; 

所以,b指向陣列a[0]。可以使用索引a[0][i]訪問數組a[0]的元素。在指針算術等效中,它是*(*(a + 0) + i) = *(*(a) + i) = *(*a + i) = (*a)[i]
在表達式(*a)[i]中轉換後的a的類型是int (*)[3],其也是b的類型。因此,也可以使用(*b)[i]訪問數組a[0]
所以,聲明

printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]); 

相當於

printf("%d %d %d\n", (*a)[0], (*a)[1], (*a)[2]); 

printf("%d %d %d\n", a[0][0], a[0][1], a[0][2]); 

現在看*b[0]。根據運營商優先權規則,*b[0]等同於*(b[0])。簡單的b[0]表示如上所述的數組a[0],並且當在表達式中使用時將數組轉換爲指向其第一個元素的指針,除了一些例外,b[0]實際上是指向表達式*(b[0])中的元素a[0][0]的指針。 *中的()取消引用此指針並給出值&a[0][0]。同樣,*b[1]*b[2]正在給出地址&a[1][0]&a[2][0]上的元素。
因此,聲明

printf("%d %d %d\n", *b[0], *b[1], *b[2]); 

相當於

printf("%d %d %d\n", *a[0], *a[1], *a[2]);  

printf("%d %d %d\n", &a[0][0], &a[0][1], &[0][2]); 

這將導致一個結論,(*b)[0]*b[0]都是同一類型的,int

0

有點遲到了,但答案似乎錯過一些重要的點。 (* b)[0]和* b [0]之間的區別是什麼?

(* b)[0]和* b [0]之間的區別是什麼?

提供b是3 int類型的指針數組,並指向一個

int (*b)[3] = a; // int a[3][3] 

避免一些混亂,讓說一個b

int a[X][Y];  // in your example, X=Y=3 
int (*b)[Y] = a; // this line probably gives some clue about what b is 

這是precedence的問題。 []優先*,這意味着

  • ,如果你不把父母*b[0]b[0]首先計算併產生int [Y],第一[Y]陣列的[X][Y],然後*應用和衰減(解除引用)變成int,該數組的第一個int爲Y
    結果(或目標)是int in a[0][0]

  • 與父母,(*b)[0]*b被評估第一產生一個int [Y],第一個,則該[0]給出[Y]的第一INT
    結果(或目標)是int in a[0][0]。再次......真的嗎?

兩個[0]是不一樣的東西!混淆來自第一個元素的*[0]收益率,但是在兩種情況下,評估順序都不相同。