2017-08-27 76 views
-2
#include<stdio.h> 
void fun1(int a[100]) 
{ 
    a[4]=1; 
} 
void main() 
{ 
    int a[2]={1,2}; 
    fun1(a); 
    printf("%d",a[4]); // Output 1 
} 

我知道當我們將數組作爲函數參數傳遞給它時,數組會被腐蝕爲指向第一個元素的指針。但是主函數中數組的大小如何增加呢?通過將數組作爲參數傳遞給函數來增加數組的大小

+6

它沒有,這只是**未定義的行爲**的情況。查看[鼻惡魔](http://www.catb.org/jargon/html/N/nasal-demons.html)以獲得替代結果。 –

+1

它不增加。 C只是不檢查大小,而且你正在讀/寫屬於who-knows-who的內存位置。 – bocko

+1

編譯器只有在擁有其他維度時纔會注意數組的長度,因此它知道如何對其進行索引。例如'void fun1(int a [] [3]);'。完成之後,如果你喜歡,你可以閱讀'a [0] [20]',但這將是未定義的行爲。 –

回答

3

按照C標準(6.7.6.3功能說明符(包括原型))

7的參數爲「」 「類型的陣列」的的聲明,應被調節到 「」合格指針輸入「」,其中類型限定符(如果有的話) 是那些在該陣列型的[和] 推導....內指定

這意味着,在聲明

void fun1(int a[100]) 
{ 
    a[4]=1; 
} 

函數參數被調整到類型int *和作爲導致實際上具有以下聲明

void fun1(int *a) 
{ 
    a[4]=1; 
} 

因此,例如,下面的函數聲明

void fun1(int a[2]); 
void fun1(int a[10]); 
void fun1(int a[100]); 

申報的功能同一個函數聲明看起來像

void fun1(int *a); 

另一方面,表達式中用作函數參數的數組隱式轉換爲指向其第一個元素的指針。因此,在用該表達此函數調用使用陣列指示符

fun1(a); 

陣列指示符a被轉換爲指針到它的第一元件和所述參數的表達式的類型int *

你可以想像這個調用下列方式

{ 
    int *temporary p = a; 
    fun1(p); 
}  

因此函數參數的類型爲int *即它是一個指針和相應的參數也是一個指針。該函數不處理數組類型的對象。它處理指針類型的對象。

因此,這兩個數組都不會增加它的大小,而且原始程序有未定義的行爲,因爲嘗試訪問超出原始數組的內存。

通過輸出參數的大小,您可以輕鬆檢查函數是否處理指針。例如

void fun1(int a[100]) 
{ 
    printf("sizeof(a) = %zu\n", sizeof(a)); 
    a[4]=1; 
} 

輸出將等於根據所使用的系統上或者48或。但在任何情況下,它都不會像您所期望的那樣等於100 * sizeof(int)

2

cant更改自動數組運行時的大小。

如果要在運行時選擇聲明自動數組的大小,可以使用(自c99)VLA

int n; 
scanf("%d", &n) 
int a[n]; 

,或者如果你真的需要改變陣列運行時的大小,你必須動態地分配在堆內存,然後realloc大小的緩衝區的。

int *a = malloc(sizeof(int) * 2); 
int *tmp = realloc(a, sizeof(int) * 4); 
if (tmp == NULL) 
{ 
    // Reallocation failed 
} 
else 
{ 
    a = tmp; 
} 

由於@DavidBowling說,它能夠更好地使用反引用標識,而不是類型的sizeof表達式。在我們的情況下,將

int *a = malloc(sizeof *a * 2); 
int *tmp = realloc(a, sizeof *tmp * 4); 

它更容易&不易出錯時,指針類型的變化。

+2

Minor nitpick:優先選擇'sizeof'表達式中的標識符超過顯式類型。當類型發生變化時,這個錯誤更少且容易維護:'int * a = malloc(sizeof * a * 2);'和int * tmp = realloc(a,sizeof * tmp * 4);'。 –

相關問題