[英]Why use “[*]” instead of “[]” in function prototype?
以下是為了在函數原型中添加用於聲明數組類型的花哨*
星形語法的理由而寫的 - 只是為了在我們進入問題之前澄清:
函數原型可以使用具有可變長度數組類型的參數(第6.5.5.2節),使用特殊語法,如
int minimum(int,int [*][*]);
這與其他C原型一致,其中不需要指定參數的名稱。
但我非常有信心我們可以通過簡單地只使用普通的陣列,像這樣未指定大小(在這里重新編寫命名的功能例如同樣的效果minimum
在上面的報價給出什么,我相信完全相同的功能(除使用size_t
而不是int
作為第一個參數,這在案例中並不重要)):
#include <stdio.h>
int minimum(size_t, int (*)[]);
int (main)()
{
size_t sz;
scanf("%zu", &sz);
int vla[sz];
for(size_t i = 0; i < sz; ++i)
vla[i] = i;
minimum(sizeof(vla) / sizeof(*vla), &vla);
int a[] = { 5, 4, 3, 2, 1, 0 };
minimum(sizeof(a) / sizeof(*a), &a);
}
int minimum(size_t a, int (*b)[a])
{
for(size_t i = 0; i < sizeof(*b) / sizeof(**b); ++i)
printf("%d ", (*b)[i]);
return printf("\n");
}
因為我很確定標准中有一些地方說明2個陣列只有在它們的大小相等時才兼容,如果它們是可變的則無關緊要。
我的觀點也得到了證實,即minimum
定義不會抱怨“沖突類型”,因為如果它的某些參數具有不兼容的類型(我不認為是這種情況,因為這兩個數組的大小都是在編譯時未指定 - 我引用minimum
的第二個參數)。
好的除此之外 - 您能指出一個[*]
單個用例,使用普通的未指定大小的數組無法替換嗎?
上面的代碼使用clang和gcc編譯時沒有任何警告。 它還產生預期的輸出。
對於任何不了解C的人(或任何認為他/她知道它的人) - 類型數組的函數參數被隱式轉換為“指向其元素類型的指針”。 所以這:
int minimum(int,int [*][*]);
調整為:
int minimum(int,int (*)[*]);
然后我認為它也可以寫成:
int minimum(int,int (*)[]);
沒有任何后果和與上述2種形式相同的行為。 從而使[*]
形式過時。
[]
只能用作多維數組最左邊的“維度說明符”,而[*]
可以在任何地方使用。
在函數參數聲明中,最左邊(僅!) [...]
無論如何都被調整為(*)
,因此可以在該位置使用(*)
,但代價是清晰度。
可以省略左下方[...]
的維度,留下空括號。 這將使數組元素類型不完整。 這不是什么大問題,因為可以在接近使用點(例如在函數定義中)完成它。
下一個[...]
需要一個不能省略的數字或*
。 這些聲明
int foo (int [*][*][*]);
int foo (int (*)[*][*]);
int foo (int (*)[ ][*]);
都是兼容的,但沒有一個兼容它們沒有將第三個維度指定為*
或數字。 如果第三維確實是變量,則*
是唯一的選擇。
因此, [*]
至少對於尺寸3及以上是必要的。
好的除此之外 - 您能指出一個[*]的單個用例,使用普通的未指定大小的數組無法替換嗎?
當您傳遞三維VLA數組時會出現這種情況:
int minimum(size_t, int [*][*][*]);
這可以寫成:
int minimum(size_t, int (*)[*][*]);
甚至使用未指定大小的數組:
int minimum(size_t, int (*)[][*]);
但是你沒有可能省略或繞過最后的指示,因此它必須在[*]
這樣的聲明中保留。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.