#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
}
我知道當我們將數組作爲函數參數傳遞給它時,數組會被腐蝕爲指向第一個元素的指針。但是主函數中數組的大小如何增加呢?通過將數組作爲參數傳遞給函數來增加數組的大小
#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
}
我知道當我們將數組作爲函數參數傳遞給它時,數組會被腐蝕爲指向第一個元素的指針。但是主函數中數組的大小如何增加呢?通過將數組作爲參數傳遞給函數來增加數組的大小
按照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;
}
輸出將等於根據所使用的系統上或者4
8
或。但在任何情況下,它都不會像您所期望的那樣等於100 * sizeof(int)
。
您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);
它更容易&不易出錯時,指針類型的變化。
Minor nitpick:優先選擇'sizeof'表達式中的標識符超過顯式類型。當類型發生變化時,這個錯誤更少且容易維護:'int * a = malloc(sizeof * a * 2);'和int * tmp = realloc(a,sizeof * tmp * 4);'。 –
它沒有,這只是**未定義的行爲**的情況。查看[鼻惡魔](http://www.catb.org/jargon/html/N/nasal-demons.html)以獲得替代結果。 –
它不增加。 C只是不檢查大小,而且你正在讀/寫屬於who-knows-who的內存位置。 – bocko
編譯器只有在擁有其他維度時纔會注意數組的長度,因此它知道如何對其進行索引。例如'void fun1(int a [] [3]);'。完成之後,如果你喜歡,你可以閱讀'a [0] [20]',但這將是未定義的行爲。 –