2

我是編程和學習數組中指針的新手。我現在有點困惑。看看下面的程序:指向數組的指針和指向指針的指針之間有什麼區別?

#include <stdio.h> 
int fun(); 
int main() 
{ 
    int num[3][3]={23,32,478,55,0,56,25,13, 80}; 
    printf("%d\n",*(*(num+0)+1)); 
    fun(num); 
    printf("%d\n", *(*(num+0)+1)); 
    *(*(num+0)+0)=23; 
    printf("%d\n",*(*(num+0))); 
    return 0; 
} 
int fun(*p) // Compilation error 
{ 
    *(p+0)=0; 
    return 0; 
} 

這是我的老師的筆記寫的程序。在main()函數中,在printf()函數中,解引用運算符被使用了兩次,因爲num是指向數組的指針,因此首次解除引用運算符將​​指向int,然後第二個指針指向該值。

我的問題是,當我將數組名稱作爲參數傳遞給函數fun()時,爲什麼使用*p;爲什麼不**p as num是一個指向數組的指針?

第二件事爲什麼*(p+0)用於更改數組的第零個元素的值;爲什麼不使用*(*(p+0)+0)=0中的main()函數*(*(num+0)+0)被用來改變零元素的值?

整件事對我來說非常混亂,但無論如何我必須理解它。我已經搜索了這個,並發現指針指向數組和指針指針之間有區別,但我不明白。

+0

多維數組是* flat *。清除有關如何實施的混淆。 – 2014-12-03 12:09:48

+0

你會從這個問題的答案得到答案http://stackoverflow.com/questions/14100240/2-dim-array-and-double-pointer?lq = 1 – 999k 2014-12-03 12:18:11

+0

難道你不會得到編譯錯誤,原型/功能不匹配?爲什麼你問+ 0 + 0而不是+0?爲什麼在代碼中添加靜態0? – dhein 2014-12-03 12:42:35

回答

1

這個例子顯示了一個矩陣,指針數組的第一個整數,指針的指針

#include<stdio.h> 
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */ 
int main() 
{ 
    /* matrix */ 
    int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}}; 
    /* three pointers to first integer of array */ 
    int *pnum[3] = {num[0], num[1], num[2]}; 
    /* pointer to pointer */ 
    int **ppnum = pnum; 
    printf("%d\n", *(*(num+1)+2)); 
    fun(num); 
    printf("%d\n", *(*(num+1)+2)); 
    pnum[1][2] = 2; 
    printf("%d\n", *(*(num+1)+2)); 
    ppnum[1][2] = 3; 
    printf("%d\n", *(*(num+1)+2)); 
    return 0; 
} 
int fun(int (*p)[3]) 
{ 
    p[1][2]=1; 
    return 0; 
} 
+1

我沒有得到任何錯誤 – user4156958 2014-12-03 12:44:35

0

你實際上並不需要任何指針在這裏印什麼。

您的int num[3][3]實際上是一個由三個元素組成的數組,每個元素都是一個由三個整數組成的數組。因此,num[0][0] = 23,num[1][1] = 0等等。因此你可以說printf("%d", num[0][0])打印數組的第一個元素。

+0

我知道我可以做到這一點,但我想知道它與指針和我的問題是,爲什麼*(P + 0)用於初始化0爲什麼不* *(*(p + 0) +0)?因爲num是指向數組的指針 – user4156958 2014-12-03 12:51:29

+0

如果您必須使用指針,那麼只需使用'p'。已知'p'是函數定義中的一個指針,所以你可以說'p = 0;''''''''''''''''''''''嘗試一下。 – Gophyr 2014-12-03 12:54:35

0

指針變量:

指針是變量,其存儲地址(的變量)。每個人都知道。


指針數組:

數組是具有相同對象的組的開始點(地址)的變量。

而指針是一個存儲數組起點(地址)的變量。

例如:

int iArray[3]; 

iArray是具有三個整數的地址值的可變和存儲器是靜態分配。以下語法以典型的編程語言提供。

// iArray[0] = *(iArray+0); 
// iArray[1] = *(iArray+1); 
// iArray[2] = *(iArray+2); 

在上面的iArray是一個變量,我們可以通過它使用上面提到的任何語法來訪問這三個整數變量。

*(iArray + 0); //這裏iArray + 0是第一個對象的地址。 * *是取消引用 *(iArray + 1); //這裏iArray + 1是第二個對象的地址。 *要解除引用

這麼簡單,有什麼可以混淆的。


以下線的理解

int iArray1[3]; 
int iArray2[3][3]; 

int *ipArray = 0; 

ipArray = iArray1;  // correct 
ipArray = iArray2[0];  // correct 
ipArray = iArray2[2];  // correct 
int **ippArray = iArray2; // wrong 

按照上面的最後一行,編譯器不會把它作爲一個有效的分配。所以** p沒有使用。

由於分配內存的方式,指針關節不能應用於雙數組。

+1

你在回答中根本沒有談到數組指針。 – newacct 2014-12-03 23:08:20

3

訣竅是陣列指針衰減:當你提到一個數組的名字時,它會在幾乎所有上下文中衰變成一個指向其第一個元素的指針。那就是num只是一個由三個整數組成的陣列(類型= int [3][3])。

讓我們分析表達式*(*(num + 1) + 2)

當您在表達式*(num + 1)中提到num時,它會衰減爲指向其第一個元素的指針,該元素是一個由三個整數組成的數組(第一個元素爲int (*)[3])。在這個指針指針算術被執行,並且指針指向的大小被添加到指針的值。在這種情況下,它是一個由三個整數組成的數組的大小(在許多機器上是12個字節)。取消引用指針後,您將剩下一個類型int [3]

但是,這種解除引用只涉及類型,因爲緊接在解引用操作之後,我們看到表達式*(/*expression of type int[3]*/ + 2),所以內部表達式衰減回到指向第一個數組元素的指針。該指針包含與num + 1產生的指針相同的地址,但它具有不同的類型:int*。因此,這個指針的指針運算會將指針前進兩個整數(8個字節)。因此,表達式*(*(num + 1) + 2)將產生整數元素,其偏移量爲12 + 8 = 20字節,這是數組中的第六個整數。


關於你關於fun()通話問題,該呼叫實際上是打破了,只有工作,因爲你的老師並沒有包括在fun()向前聲明的參數。代碼

int fun(int* arg); 

int main() { 
    int num[3][3] = ...; 
    ... 
    fun(num); 
} 

由於錯誤的指針類型會產生編譯時錯誤。由於指向num中第一個數組的指針與指向num中第一個數組的第一個元素的指針相同,因此您的教師的代碼「工作」。即他的代碼相當於

int fun(int* arg); 

int main() { 
    int num[3][3] = ...; 
    ... 
    //both calls are equivalent 
    fun(num[0]); 
    fun(&num[0][0]); 
} 

這將編譯沒有錯誤。

相關問題